My Project
output_structure.cpp
Go to the documentation of this file.
1 
38 #include "../include/output_structure.hpp"
39 
41 
44 
45  unsigned short iDim, iZone, iSpan, iMarker;
46 
47  /*--- Initialize point and connectivity counters to zero. ---*/
48 
49  nGlobal_Poin = 0;
50  nSurf_Poin = 0;
51  nGlobal_Elem = 0;
52  nSurf_Elem = 0;
53  nGlobal_Tria = 0;
54  nGlobal_Quad = 0;
55  nGlobal_Tetr = 0;
56  nGlobal_Hexa = 0;
57  nGlobal_Pris = 0;
58  nGlobal_Pyra = 0;
59  nGlobal_Line = 0;
60  nGlobal_BoundTria = 0;
61  nGlobal_BoundQuad = 0;
62 
63  /*--- Initialize pointers to NULL ---*/
64 
65  Coords = NULL;
66  Conn_Line = NULL; Conn_BoundTria = NULL; Conn_BoundQuad = NULL;
67  Conn_Tria = NULL; Conn_Quad = NULL; Conn_Tetr = NULL;
68  Conn_Hexa = NULL; Conn_Pris = NULL; Conn_Pyra = NULL;
69  Data = NULL;
70 
71  /*--- Initialize parallel pointers to NULL ---*/
72 
73  nGlobal_Poin_Par = 0;
74  nGlobal_Elem_Par = 0;
75  nGlobal_Surf_Poin = 0;
76  nParallel_Poin = 0;
77  nSurf_Poin_Par = 0;
78  nSurf_Elem_Par = 0;
79  nParallel_Tria = 0;
80  nParallel_Quad = 0;
81  nParallel_Tetr = 0;
82  nParallel_Hexa = 0;
83  nParallel_Pris = 0;
84  nParallel_Pyra = 0;
85  nParallel_Line = 0;
86  nParallel_BoundTria = 0;
87  nParallel_BoundQuad = 0;
88 
89  /*--- Initialize pointers to NULL ---*/
90 
91  Conn_BoundLine_Par = NULL; Conn_BoundTria_Par = NULL; Conn_BoundQuad_Par = NULL;
92  Conn_Tria_Par = NULL; Conn_Quad_Par = NULL; Conn_Tetr_Par = NULL;
93  Conn_Hexa_Par = NULL; Conn_Pris_Par = NULL; Conn_Pyra_Par = NULL;
94 
95  Local_Data = NULL;
96  Local_Data_Copy = NULL;
97  Parallel_Data = NULL;
98  Parallel_Surf_Data = NULL;
99 
100  /*--- Initialize structures for storing linear partitioning offsets ---*/
101 
102  nGlobalPoint_Sort = 0;
103  nLocalPoint_Sort = 0;
104  nPoint_Restart = 0;
105 
106  Local_Halo_Sort = NULL;
107 
108  beg_node = NULL;
109  end_node = NULL;
110 
111  nPoint_Lin = NULL;
112  nPoint_Cum = NULL;
113 
114  /*--- Inlet profile data structures. ---*/
115 
116  nRow_InletFile = NULL;
117  nRowCum_InletFile = NULL;
118  InletCoords = NULL;
119 
120  Marker_Tags_InletFile.clear();
121 
122  /*--- Initialize CGNS write flag ---*/
123 
124  wrote_base_file = false;
125 
126  /*--- Initialize CGNS write flag ---*/
127 
128  wrote_CGNS_base = false;
129 
130  /*--- Initialize Tecplot surface flag ---*/
131 
132  wrote_surf_file = false;
133 
134  /*--- Initialize Paraview write flag ---*/
135 
136  wrote_Paraview_base = false;
137 
138  /*--- Initialize residual ---*/
139 
140  RhoRes_New = EPS;
141  RhoRes_Old = new su2double[config->GetnZone()];
142  for (iZone = 0; iZone < config->GetnZone(); iZone++) RhoRes_Old[iZone] = EPS;
143 
144  wrote_Paraview_base = false;
145 
146  /*--- Initialize turbo flag ---*/
147  turbo = config->GetBoolTurbomachinery();
148 
149  if(turbo){
150  /*--- Initializate quantities for turboperformace ---*/
151  nSpanWiseSections = config->GetnSpanMaxAllZones();
152  nMarkerTurboPerf = config->GetnMarker_TurboPerformance();
153 
154 
155  TotalStaticEfficiency = new su2double*[nMarkerTurboPerf];
156  TotalTotalEfficiency = new su2double*[nMarkerTurboPerf];
157  KineticEnergyLoss = new su2double*[nMarkerTurboPerf];
158  TRadius = new su2double*[nMarkerTurboPerf];
159  TotalPressureLoss = new su2double*[nMarkerTurboPerf];
160  MassFlowIn = new su2double*[nMarkerTurboPerf];
161  MassFlowOut = new su2double*[nMarkerTurboPerf];
162  FlowAngleIn = new su2double*[nMarkerTurboPerf];
163  FlowAngleIn_BC = new su2double*[nMarkerTurboPerf];
164  FlowAngleOut = new su2double*[nMarkerTurboPerf];
165  EulerianWork = new su2double*[nMarkerTurboPerf];
166  TotalEnthalpyIn = new su2double*[nMarkerTurboPerf];
167  TotalEnthalpyIn_BC = new su2double*[nMarkerTurboPerf];
168  EntropyIn = new su2double*[nMarkerTurboPerf];
169  EntropyOut = new su2double*[nMarkerTurboPerf];
170  EntropyIn_BC = new su2double*[nMarkerTurboPerf];
171  PressureRatio = new su2double*[nMarkerTurboPerf];
172  TotalTemperatureIn = new su2double*[nMarkerTurboPerf];
173  EnthalpyOut = new su2double*[nMarkerTurboPerf];
174  MachIn = new su2double**[nMarkerTurboPerf];
175  MachOut = new su2double**[nMarkerTurboPerf];
176  VelocityOutIs = new su2double*[nMarkerTurboPerf];
177  DensityIn = new su2double*[nMarkerTurboPerf];
178  PressureIn = new su2double*[nMarkerTurboPerf];
179  TurboVelocityIn = new su2double**[nMarkerTurboPerf];
180  DensityOut = new su2double*[nMarkerTurboPerf];
181  PressureOut = new su2double*[nMarkerTurboPerf];
182  TurboVelocityOut = new su2double**[nMarkerTurboPerf];
183  EnthalpyOutIs = new su2double*[nMarkerTurboPerf];
184  EntropyGen = new su2double*[nMarkerTurboPerf];
185  AbsFlowAngleIn = new su2double*[nMarkerTurboPerf];
186  TotalEnthalpyOut = new su2double*[nMarkerTurboPerf];
187  TotalEnthalpyOutIs = new su2double*[nMarkerTurboPerf];
188  RothalpyIn = new su2double*[nMarkerTurboPerf];
189  RothalpyOut = new su2double*[nMarkerTurboPerf];
190  AbsFlowAngleOut = new su2double*[nMarkerTurboPerf];
191  PressureOut_BC = new su2double*[nMarkerTurboPerf];
192  TemperatureIn = new su2double*[nMarkerTurboPerf];
193  TemperatureOut = new su2double*[nMarkerTurboPerf];
194  TotalPressureIn = new su2double*[nMarkerTurboPerf];
195  TotalPressureOut = new su2double*[nMarkerTurboPerf];
196  TotalTemperatureOut = new su2double*[nMarkerTurboPerf];
197  EnthalpyIn = new su2double*[nMarkerTurboPerf];
198  TurbIntensityIn = new su2double*[nMarkerTurboPerf];
199  Turb2LamViscRatioIn = new su2double*[nMarkerTurboPerf];
200  TurbIntensityOut = new su2double*[nMarkerTurboPerf];
201  Turb2LamViscRatioOut = new su2double*[nMarkerTurboPerf];
202  NuFactorIn = new su2double*[nMarkerTurboPerf];
203  NuFactorOut = new su2double*[nMarkerTurboPerf];
204 
205  for (iMarker = 0; iMarker < nMarkerTurboPerf; iMarker++){
206  TotalStaticEfficiency [iMarker] = new su2double [nSpanWiseSections + 1];
207  TotalTotalEfficiency [iMarker] = new su2double [nSpanWiseSections + 1];
208  KineticEnergyLoss [iMarker] = new su2double [nSpanWiseSections + 1];
209  TRadius [iMarker] = new su2double [nSpanWiseSections + 1];
210  TotalPressureLoss [iMarker] = new su2double [nSpanWiseSections + 1];
211  MassFlowIn [iMarker] = new su2double [nSpanWiseSections + 1];
212  MassFlowOut [iMarker] = new su2double [nSpanWiseSections + 1];
213  FlowAngleIn [iMarker] = new su2double [nSpanWiseSections + 1];
214  FlowAngleIn_BC [iMarker] = new su2double [nSpanWiseSections + 1];
215  FlowAngleOut [iMarker] = new su2double [nSpanWiseSections + 1];
216  EulerianWork [iMarker] = new su2double [nSpanWiseSections + 1];
217  TotalEnthalpyIn [iMarker] = new su2double [nSpanWiseSections + 1];
218  TotalEnthalpyIn_BC [iMarker] = new su2double [nSpanWiseSections + 1];
219  EntropyIn [iMarker] = new su2double [nSpanWiseSections + 1];
220  EntropyOut [iMarker] = new su2double [nSpanWiseSections + 1];
221  EntropyIn_BC [iMarker] = new su2double [nSpanWiseSections + 1];
222  PressureRatio [iMarker] = new su2double [nSpanWiseSections + 1];
223  TotalTemperatureIn [iMarker] = new su2double [nSpanWiseSections + 1];
224  EnthalpyOut [iMarker] = new su2double [nSpanWiseSections + 1];
225  MachIn [iMarker] = new su2double*[nSpanWiseSections + 1];
226  MachOut [iMarker] = new su2double*[nSpanWiseSections + 1];
227  VelocityOutIs [iMarker] = new su2double [nSpanWiseSections + 1];
228  DensityIn [iMarker] = new su2double [nSpanWiseSections + 1];
229  PressureIn [iMarker] = new su2double [nSpanWiseSections + 1];
230  TurboVelocityIn [iMarker] = new su2double*[nSpanWiseSections + 1];
231  DensityOut [iMarker] = new su2double [nSpanWiseSections + 1];
232  PressureOut [iMarker] = new su2double [nSpanWiseSections + 1];
233  TurboVelocityOut [iMarker] = new su2double*[nSpanWiseSections + 1];
234  EnthalpyOutIs [iMarker] = new su2double [nSpanWiseSections + 1];
235  EntropyGen [iMarker] = new su2double [nSpanWiseSections + 1];
236  AbsFlowAngleIn [iMarker] = new su2double [nSpanWiseSections + 1];
237  TotalEnthalpyOut [iMarker] = new su2double [nSpanWiseSections + 1];
238  TotalEnthalpyOutIs [iMarker] = new su2double [nSpanWiseSections + 1];
239  RothalpyIn [iMarker] = new su2double [nSpanWiseSections + 1];
240  RothalpyOut [iMarker] = new su2double [nSpanWiseSections + 1];
241  AbsFlowAngleOut [iMarker] = new su2double [nSpanWiseSections + 1];
242  PressureOut_BC [iMarker] = new su2double [nSpanWiseSections + 1];
243  TemperatureIn [iMarker] = new su2double [nSpanWiseSections + 1];
244  TemperatureOut [iMarker] = new su2double [nSpanWiseSections + 1];
245  TotalPressureIn [iMarker] = new su2double [nSpanWiseSections + 1];
246  TotalPressureOut [iMarker] = new su2double [nSpanWiseSections + 1];
247  TotalTemperatureOut [iMarker] = new su2double [nSpanWiseSections + 1];
248  EnthalpyIn [iMarker] = new su2double [nSpanWiseSections + 1];
249  TurbIntensityIn [iMarker] = new su2double [nSpanWiseSections + 1];
250  Turb2LamViscRatioIn [iMarker] = new su2double [nSpanWiseSections + 1];
251  TurbIntensityOut [iMarker] = new su2double [nSpanWiseSections + 1];
252  Turb2LamViscRatioOut [iMarker] = new su2double [nSpanWiseSections + 1];
253  NuFactorIn [iMarker] = new su2double [nSpanWiseSections + 1];
254  NuFactorOut [iMarker] = new su2double [nSpanWiseSections + 1];
255 
256 
257  for (iSpan = 0; iSpan < nSpanWiseSections + 1; iSpan++){
258  TotalStaticEfficiency [iMarker][iSpan] = 0.0;
259  TotalTotalEfficiency [iMarker][iSpan] = 0.0;
260  KineticEnergyLoss [iMarker][iSpan] = 0.0;
261  TRadius [iMarker][iSpan] = 0.0;
262  TotalPressureLoss [iMarker][iSpan] = 0.0;
263  MassFlowIn [iMarker][iSpan] = 0.0;
264  MassFlowOut [iMarker][iSpan] = 0.0;
265  FlowAngleIn [iMarker][iSpan] = 0.0;
266  FlowAngleIn_BC [iMarker][iSpan] = config->GetFlowAngleIn_BC();
267  FlowAngleOut [iMarker][iSpan] = 0.0;
268  EulerianWork [iMarker][iSpan] = 0.0;
269  TotalEnthalpyIn [iMarker][iSpan] = 0.0;
270  TotalEnthalpyIn_BC [iMarker][iSpan] = 0.0;
271  EntropyIn [iMarker][iSpan] = 0.0;
272  EntropyOut [iMarker][iSpan] = 0.0;
273  EntropyIn_BC [iMarker][iSpan] = 0.0;
274  PressureRatio [iMarker][iSpan] = 0.0;
275  TotalTemperatureIn [iMarker][iSpan] = 0.0;
276  EnthalpyOut [iMarker][iSpan] = 0.0;
277 
278 
279  VelocityOutIs [iMarker][iSpan] = 0.0;
280  DensityIn [iMarker][iSpan] = 0.0;
281  PressureIn [iMarker][iSpan] = 0.0;
282 
283  DensityOut [iMarker][iSpan] = 0.0;
284  PressureOut [iMarker][iSpan] = 0.0;
285 
286  EnthalpyOutIs [iMarker][iSpan] = 0.0;
287  EntropyGen [iMarker][iSpan] = 0.0;
288  AbsFlowAngleIn [iMarker][iSpan] = 0.0;
289  TotalEnthalpyOut [iMarker][iSpan] = 0.0;
290  TotalEnthalpyOutIs [iMarker][iSpan] = 0.0;
291  RothalpyIn [iMarker][iSpan] = 0.0;
292  RothalpyOut [iMarker][iSpan] = 0.0;
293  AbsFlowAngleOut [iMarker][iSpan] = 0.0;
294  PressureOut_BC [iMarker][iSpan] = config->GetPressureOut_BC();
295 
296  TemperatureIn [iMarker][iSpan] = 0.0;
297  TemperatureOut [iMarker][iSpan] = 0.0;
298  TotalPressureIn [iMarker][iSpan] = 0.0;
299  TotalPressureOut [iMarker][iSpan] = 0.0;
300  TotalTemperatureOut [iMarker][iSpan] = 0.0;
301  EnthalpyIn [iMarker][iSpan] = 0.0;
302  TurbIntensityIn [iMarker][iSpan] = 0.0;
303  Turb2LamViscRatioIn [iMarker][iSpan] = 0.0;
304  TurbIntensityOut [iMarker][iSpan] = 0.0;
305  Turb2LamViscRatioOut [iMarker][iSpan] = 0.0;
306  NuFactorIn [iMarker][iSpan] = 0.0;
307  NuFactorOut [iMarker][iSpan] = 0.0;
308  MachIn [iMarker][iSpan] = new su2double[4];
309  MachOut [iMarker][iSpan] = new su2double[4];
310  TurboVelocityIn [iMarker][iSpan] = new su2double[4];
311  TurboVelocityOut [iMarker][iSpan] = new su2double[4];
312 
313  for (iDim = 0; iDim < 4; iDim++){
314  MachIn [iMarker][iSpan][iDim] = 0.0;
315  MachOut [iMarker][iSpan][iDim] = 0.0;
316  TurboVelocityIn [iMarker][iSpan][iDim] = 0.0;
317  TurboVelocityOut [iMarker][iSpan][iDim] = 0.0;
318  }
319  }
320  }
321  }
322 }
323 
325  /* delete pointers initialized at construction*/
326  /* Coords and Conn_*(Connectivity) have their own dealloc functions */
327  /* Data is taken care of in DeallocateSolution function */
328 
329  if (RhoRes_Old != NULL) delete [] RhoRes_Old;
330 
331  /*--- Delete turboperformance pointers initiliazed at constrction ---*/
332  unsigned short iMarker, iSpan;
333  if(turbo){
334  for(iMarker = 0; iMarker< nMarkerTurboPerf; iMarker++){
335  for(iSpan=0; iSpan<nSpanWiseSections+1; iSpan++){
336  delete [] MachIn [iMarker][iSpan];
337  delete [] MachOut [iMarker][iSpan];
338  delete [] TurboVelocityIn [iMarker][iSpan];
339  delete [] TurboVelocityOut[iMarker][iSpan];
340  }
341  }
342  for(iMarker = 0; iMarker< nMarkerTurboPerf; iMarker++){
343  delete [] TotalStaticEfficiency[iMarker];
344  delete [] TotalTotalEfficiency [iMarker];
345  delete [] KineticEnergyLoss [iMarker];
346  delete [] TRadius [iMarker];
347  delete [] TotalPressureLoss [iMarker];
348  delete [] MassFlowIn [iMarker];
349  delete [] MassFlowOut [iMarker];
350  delete [] FlowAngleIn [iMarker];
351  delete [] FlowAngleOut [iMarker];
352  delete [] EulerianWork [iMarker];
353  delete [] TotalEnthalpyIn [iMarker];
354  delete [] TotalEnthalpyOut [iMarker];
355  delete [] TotalEnthalpyOutIs [iMarker];
356  delete [] PressureRatio [iMarker];
357  delete [] EnthalpyOut [iMarker];
358  delete [] VelocityOutIs [iMarker];
359  delete [] TotalTemperatureIn [iMarker];
360  delete [] FlowAngleIn_BC [iMarker];
361  delete [] EntropyIn [iMarker];
362  delete [] EntropyIn_BC [iMarker];
363  delete [] EntropyOut [iMarker];
364  delete [] TotalEnthalpyIn_BC [iMarker];
365  delete [] DensityIn [iMarker];
366  delete [] PressureIn [iMarker];
367  delete [] DensityOut [iMarker];
368  delete [] PressureOut [iMarker];
369  delete [] EnthalpyOutIs [iMarker];
370  delete [] EntropyGen [iMarker];
371  delete [] AbsFlowAngleIn [iMarker];
372  delete [] RothalpyIn [iMarker];
373  delete [] RothalpyOut [iMarker];
374  delete [] AbsFlowAngleOut [iMarker];
375  delete [] PressureOut_BC [iMarker];
376  delete [] MachIn [iMarker];
377  delete [] MachOut [iMarker];
378  delete [] TurboVelocityIn [iMarker];
379  delete [] TurboVelocityOut [iMarker];
380  delete [] TemperatureIn [iMarker];
381  delete [] TemperatureOut [iMarker];
382  delete [] TotalPressureIn [iMarker];
383  delete [] TotalPressureOut [iMarker];
384  delete [] TotalTemperatureOut [iMarker];
385  delete [] EnthalpyIn [iMarker];
386  delete [] TurbIntensityIn [iMarker];
387  delete [] Turb2LamViscRatioIn [iMarker];
388  delete [] TurbIntensityOut [iMarker];
389  delete [] Turb2LamViscRatioOut [iMarker];
390  delete [] NuFactorIn [iMarker];
391  delete [] NuFactorOut [iMarker];
392 
393 
394  }
395  delete [] TotalStaticEfficiency;
396  delete [] TotalTotalEfficiency;
397  delete [] KineticEnergyLoss;
398  delete [] TRadius;
399  delete [] TotalPressureLoss;
400  delete [] MassFlowIn;
401  delete [] MassFlowOut;
402  delete [] FlowAngleIn;
403  delete [] FlowAngleOut;
404  delete [] EulerianWork;
405  delete [] TotalEnthalpyIn;
406  delete [] TotalEnthalpyOut;
407  delete [] TotalEnthalpyOutIs;
408  delete [] PressureRatio;
409  delete [] EnthalpyOut;
410  delete [] VelocityOutIs;
411  delete [] TotalTemperatureIn;
412  delete [] FlowAngleIn_BC;
413  delete [] EntropyIn;
414  delete [] EntropyIn_BC;
415  delete [] EntropyOut;
416  delete [] TotalEnthalpyIn_BC;
417  delete [] DensityIn;
418  delete [] PressureIn;
419  delete [] DensityOut;
420  delete [] PressureOut;
421  delete [] EnthalpyOutIs;
422  delete [] EntropyGen;
423  delete [] AbsFlowAngleIn;
424  delete [] RothalpyIn;
425  delete [] RothalpyOut;
426  delete [] AbsFlowAngleOut;
427  delete [] PressureOut_BC;
428  delete [] MachIn;
429  delete [] MachOut;
430  delete [] TurboVelocityIn;
431  delete [] TurboVelocityOut;
432  delete [] TemperatureIn;
433  delete [] TemperatureOut;
434  delete [] TotalPressureIn;
435  delete [] TotalPressureOut;
436  delete [] TotalTemperatureOut;
437  delete [] EnthalpyIn;
438  delete [] TurbIntensityIn;
439  delete [] Turb2LamViscRatioIn;
440  delete [] TurbIntensityOut;
441  delete [] Turb2LamViscRatioOut;
442  delete [] NuFactorIn;
443  delete [] NuFactorOut;
444  }
445 }
446 
448  CSolver *FlowSolver, unsigned long iExtIter,
449  unsigned short val_iZone, unsigned short val_iInst) {
450 
451  unsigned short iMarker;
452  unsigned long iPoint, iVertex, Global_Index;
453  su2double PressCoeff = 0.0, SkinFrictionCoeff[3], HeatFlux;
454  su2double xCoord = 0.0, yCoord = 0.0, zCoord = 0.0, Mach, Pressure;
455  char cstr[200];
456 
457  unsigned short solver = config->GetKind_Solver();
458  unsigned short nDim = geometry->GetnDim();
459 
460 #ifndef HAVE_MPI
461 
462  unsigned short iDim;
463  char buffer [50];
464  ofstream SurfFlow_file;
465 
466  /*--- Write file name with extension if unsteady ---*/
467  strcpy (cstr, config->GetSurfFlowCoeff_FileName().c_str());
468 
469  if (config->GetUnsteady_Simulation() == HARMONIC_BALANCE) {
470  SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(val_iInst));
471 
472  }else if (config->GetUnsteady_Simulation() && config->GetWrt_Unsteady()) {
473  if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.csv", SU2_TYPE::Int(iExtIter));
474  if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d.csv", SU2_TYPE::Int(iExtIter));
475  if ((SU2_TYPE::Int(iExtIter) >= 100) && (SU2_TYPE::Int(iExtIter) < 1000)) SPRINTF (buffer, "_00%d.csv", SU2_TYPE::Int(iExtIter));
476  if ((SU2_TYPE::Int(iExtIter) >= 1000) && (SU2_TYPE::Int(iExtIter) < 10000)) SPRINTF (buffer, "_0%d.csv", SU2_TYPE::Int(iExtIter));
477  if (SU2_TYPE::Int(iExtIter) >= 10000) SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(iExtIter));
478  }
479  else
480  SPRINTF (buffer, ".csv");
481 
482  strcat (cstr, buffer);
483  SurfFlow_file.precision(15);
484  SurfFlow_file.open(cstr, ios::out);
485 
486  SurfFlow_file << "\"Global_Index\", \"x_coord\", \"y_coord\", ";
487  if (nDim == 3) SurfFlow_file << "\"z_coord\", ";
488  SurfFlow_file << "\"Pressure\", \"Pressure_Coefficient\", ";
489 
490  switch (solver) {
491  case EULER : SurfFlow_file << "\"Mach_Number\"" << "\n"; break;
492  case NAVIER_STOKES: case RANS:
493  if (nDim == 2) SurfFlow_file << "\"Skin_Friction_Coefficient_X\", \"Skin_Friction_Coefficient_Y\", \"Heat_Flux\"" << "\n";
494  if (nDim == 3) SurfFlow_file << "\"Skin_Friction_Coefficient_X\", \"Skin_Friction_Coefficient_Y\", \"Skin_Friction_Coefficient_Z\", \"Heat_Flux\"" << "\n";
495  break;
496  }
497 
498  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
499  if (config->GetMarker_All_Plotting(iMarker) == YES) {
500  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
501  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
502  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
503  xCoord = geometry->node[iPoint]->GetCoord(0);
504  yCoord = geometry->node[iPoint]->GetCoord(1);
505  if (nDim == 3) zCoord = geometry->node[iPoint]->GetCoord(2);
506 
507  /*--- The output should be in inches ---*/
508 
509  if (config->GetSystemMeasurements() == US) {
510  xCoord *= 12.0; yCoord *= 12.0;
511  if (nDim == 3) zCoord *= 12.0;
512  }
513 
514  Pressure = FlowSolver->node[iPoint]->GetPressure();
515  PressCoeff = FlowSolver->GetCPressure(iMarker, iVertex);
516  SurfFlow_file << scientific << Global_Index << ", " << xCoord << ", " << yCoord << ", ";
517  if (nDim == 3) SurfFlow_file << scientific << zCoord << ", ";
518  SurfFlow_file << scientific << Pressure << ", " << PressCoeff << ", ";
519  switch (solver) {
520  case EULER : case FEM_EULER:
521  Mach = sqrt(FlowSolver->node[iPoint]->GetVelocity2()) / FlowSolver->node[iPoint]->GetSoundSpeed();
522  SurfFlow_file << scientific << Mach << "\n";
523  break;
524  case NAVIER_STOKES: case RANS: case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES:
525  for (iDim = 0; iDim < nDim; iDim++)
526  SkinFrictionCoeff[iDim] = FlowSolver->GetCSkinFriction(iMarker, iVertex, iDim);
527  HeatFlux = FlowSolver->GetHeatFlux(iMarker, iVertex);
528 
529  if (nDim == 2) SurfFlow_file << scientific << SkinFrictionCoeff[0] << ", " << SkinFrictionCoeff[1] << ", " << HeatFlux << "\n";
530  if (nDim == 3) SurfFlow_file << scientific << SkinFrictionCoeff[0] << ", " << SkinFrictionCoeff[1] << ", " << SkinFrictionCoeff[2] << ", " << HeatFlux << "\n";
531 
532  break;
533  }
534  }
535  }
536  }
537 
538  SurfFlow_file.close();
539 
540 #else
541 
542  int iProcessor, nProcessor = size;
543 
544  unsigned long Buffer_Send_nVertex[1], *Buffer_Recv_nVertex = NULL;
545  unsigned long nVertex_Surface = 0, nLocalVertex_Surface = 0;
546  unsigned long MaxLocalVertex_Surface = 0;
547 
548  /*--- Find the max number of surface vertices among all
549  partitions and set up buffers. The master node will handle the
550  writing of the CSV file after gathering all of the data. ---*/
551 
552  nLocalVertex_Surface = 0;
553  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
554  if (config->GetMarker_All_Plotting(iMarker) == YES)
555  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
556  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
557  if (geometry->node[iPoint]->GetDomain()) nLocalVertex_Surface++;
558  }
559 
560  /*--- Communicate the number of local vertices on each partition
561  to the master node ---*/
562 
563  Buffer_Send_nVertex[0] = nLocalVertex_Surface;
564  if (rank == MASTER_NODE) Buffer_Recv_nVertex = new unsigned long [nProcessor];
565 
566  SU2_MPI::Allreduce(&nLocalVertex_Surface, &MaxLocalVertex_Surface, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
567  SU2_MPI::Gather(&Buffer_Send_nVertex, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nVertex, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
568 
569  /*--- Send and Recv buffers ---*/
570 
571  su2double *Buffer_Send_Coord_x = new su2double [MaxLocalVertex_Surface];
572  su2double *Buffer_Recv_Coord_x = NULL;
573 
574  su2double *Buffer_Send_Coord_y = new su2double [MaxLocalVertex_Surface];
575  su2double *Buffer_Recv_Coord_y = NULL;
576 
577  su2double *Buffer_Send_Coord_z = new su2double [MaxLocalVertex_Surface];
578  su2double *Buffer_Recv_Coord_z = NULL;
579 
580  su2double *Buffer_Send_Press = new su2double [MaxLocalVertex_Surface];
581  su2double *Buffer_Recv_Press = NULL;
582 
583  su2double *Buffer_Send_CPress = new su2double [MaxLocalVertex_Surface];
584  su2double *Buffer_Recv_CPress = NULL;
585 
586  su2double *Buffer_Send_Mach = new su2double [MaxLocalVertex_Surface];
587  su2double *Buffer_Recv_Mach = NULL;
588 
589  su2double *Buffer_Send_SkinFriction_x = new su2double [MaxLocalVertex_Surface];
590  su2double *Buffer_Recv_SkinFriction_x = NULL;
591 
592  su2double *Buffer_Send_SkinFriction_y = new su2double [MaxLocalVertex_Surface];
593  su2double *Buffer_Recv_SkinFriction_y = NULL;
594 
595  su2double *Buffer_Send_SkinFriction_z = new su2double [MaxLocalVertex_Surface];
596  su2double *Buffer_Recv_SkinFriction_z = NULL;
597 
598  su2double *Buffer_Send_HeatTransfer = new su2double [MaxLocalVertex_Surface];
599  su2double *Buffer_Recv_HeatTransfer = NULL;
600 
601  unsigned long *Buffer_Send_GlobalIndex = new unsigned long [MaxLocalVertex_Surface];
602  unsigned long *Buffer_Recv_GlobalIndex = NULL;
603 
604  /*--- Prepare the receive buffers on the master node only. ---*/
605 
606  if (rank == MASTER_NODE) {
607  Buffer_Recv_Coord_x = new su2double [nProcessor*MaxLocalVertex_Surface];
608  Buffer_Recv_Coord_y = new su2double [nProcessor*MaxLocalVertex_Surface];
609  if (nDim == 3) Buffer_Recv_Coord_z = new su2double [nProcessor*MaxLocalVertex_Surface];
610  Buffer_Recv_Press = new su2double [nProcessor*MaxLocalVertex_Surface];
611  Buffer_Recv_CPress = new su2double [nProcessor*MaxLocalVertex_Surface];
612  Buffer_Recv_Mach = new su2double [nProcessor*MaxLocalVertex_Surface];
613  Buffer_Recv_SkinFriction_x = new su2double [nProcessor*MaxLocalVertex_Surface];
614  Buffer_Recv_SkinFriction_y = new su2double [nProcessor*MaxLocalVertex_Surface];
615  if (nDim == 3) Buffer_Recv_SkinFriction_z = new su2double [nProcessor*MaxLocalVertex_Surface];
616  Buffer_Recv_HeatTransfer = new su2double [nProcessor*MaxLocalVertex_Surface];
617  Buffer_Recv_GlobalIndex = new unsigned long [nProcessor*MaxLocalVertex_Surface];
618  }
619 
620  /*--- Loop over all vertices in this partition and load the
621  data of the specified type into the buffer to be sent to
622  the master node. ---*/
623 
624  nVertex_Surface = 0;
625  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
626  if (config->GetMarker_All_Plotting(iMarker) == YES)
627  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
628  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
629  if (geometry->node[iPoint]->GetDomain()) {
630  Buffer_Send_Press[nVertex_Surface] = FlowSolver->node[iPoint]->GetPressure();
631  Buffer_Send_CPress[nVertex_Surface] = FlowSolver->GetCPressure(iMarker, iVertex);
632  Buffer_Send_Coord_x[nVertex_Surface] = geometry->node[iPoint]->GetCoord(0);
633  Buffer_Send_Coord_y[nVertex_Surface] = geometry->node[iPoint]->GetCoord(1);
634  if (nDim == 3) { Buffer_Send_Coord_z[nVertex_Surface] = geometry->node[iPoint]->GetCoord(2); }
635 
636  /*--- If US system, the output should be in inches ---*/
637 
638  if (config->GetSystemMeasurements() == US) {
639  Buffer_Send_Coord_x[nVertex_Surface] *= 12.0;
640  Buffer_Send_Coord_y[nVertex_Surface] *= 12.0;
641  if (nDim == 3) Buffer_Send_Coord_z[nVertex_Surface] *= 12.0;
642  }
643 
644  Buffer_Send_GlobalIndex[nVertex_Surface] = geometry->node[iPoint]->GetGlobalIndex();
645 
646  if (solver == EULER || solver == FEM_EULER)
647  Buffer_Send_Mach[nVertex_Surface] = sqrt(FlowSolver->node[iPoint]->GetVelocity2()) / FlowSolver->node[iPoint]->GetSoundSpeed();
648 
649  if (solver == NAVIER_STOKES || solver == RANS ||
650  solver == FEM_NAVIER_STOKES || solver == FEM_RANS || solver == FEM_LES) {
651  Buffer_Send_SkinFriction_x[nVertex_Surface] = FlowSolver->GetCSkinFriction(iMarker, iVertex, 0);
652  Buffer_Send_SkinFriction_y[nVertex_Surface] = FlowSolver->GetCSkinFriction(iMarker, iVertex, 1);
653  if (nDim == 3) Buffer_Send_SkinFriction_z[nVertex_Surface] = FlowSolver->GetCSkinFriction(iMarker, iVertex, 2);
654  Buffer_Send_HeatTransfer[nVertex_Surface] = FlowSolver->GetHeatFlux(iMarker, iVertex);
655  }
656  nVertex_Surface++;
657  }
658  }
659 
660  /*--- Send the information to the master node ---*/
661 
662  SU2_MPI::Gather(Buffer_Send_Coord_x, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_x, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
663  SU2_MPI::Gather(Buffer_Send_Coord_y, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_y, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
664  if (nDim == 3) SU2_MPI::Gather(Buffer_Send_Coord_z, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_z, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
665  SU2_MPI::Gather(Buffer_Send_Press, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Press, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
666  SU2_MPI::Gather(Buffer_Send_CPress, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_CPress, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
667  if (solver == EULER || solver == FEM_EULER) SU2_MPI::Gather(Buffer_Send_Mach, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Mach, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
668  if ((solver == NAVIER_STOKES) || (solver == RANS) || (solver == FEM_NAVIER_STOKES) || (solver == FEM_RANS) || (solver == FEM_LES)) {
669  SU2_MPI::Gather(Buffer_Send_SkinFriction_x, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_SkinFriction_x, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
670  SU2_MPI::Gather(Buffer_Send_SkinFriction_y, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_SkinFriction_y, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
671  if (nDim == 3) SU2_MPI::Gather(Buffer_Send_SkinFriction_z, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_SkinFriction_z, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
672  SU2_MPI::Gather(Buffer_Send_HeatTransfer, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_HeatTransfer, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
673  }
674  SU2_MPI::Gather(Buffer_Send_GlobalIndex, MaxLocalVertex_Surface, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, MaxLocalVertex_Surface, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
675 
676  /*--- The master node unpacks the data and writes the surface CSV file ---*/
677 
678  if (rank == MASTER_NODE) {
679 
680  /*--- Write file name with extension if unsteady ---*/
681  char buffer[50];
682  string filename = config->GetSurfFlowCoeff_FileName();
683  ofstream SurfFlow_file;
684 
685  /*--- Write file name with extension if unsteady ---*/
686  strcpy (cstr, filename.c_str());
687  if (config->GetUnsteady_Simulation() == HARMONIC_BALANCE) {
688  SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(val_iInst));
689 
690  } else if (config->GetUnsteady_Simulation() && config->GetWrt_Unsteady()) {
691  if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.csv", SU2_TYPE::Int(iExtIter));
692  if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d.csv", SU2_TYPE::Int(iExtIter));
693  if ((SU2_TYPE::Int(iExtIter) >= 100) && (SU2_TYPE::Int(iExtIter) < 1000)) SPRINTF (buffer, "_00%d.csv", SU2_TYPE::Int(iExtIter));
694  if ((SU2_TYPE::Int(iExtIter) >= 1000) && (SU2_TYPE::Int(iExtIter) < 10000)) SPRINTF (buffer, "_0%d.csv", SU2_TYPE::Int(iExtIter));
695  if (SU2_TYPE::Int(iExtIter) >= 10000) SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(iExtIter));
696  }
697  else
698  SPRINTF (buffer, ".csv");
699 
700  strcat (cstr, buffer);
701  SurfFlow_file.precision(15);
702  SurfFlow_file.open(cstr, ios::out);
703 
704  SurfFlow_file << "\"Global_Index\", \"x_coord\", \"y_coord\", ";
705  if (nDim == 3) SurfFlow_file << "\"z_coord\", ";
706  SurfFlow_file << "\"Pressure\", \"Pressure_Coefficient\", ";
707 
708  switch (solver) {
709  case EULER : case FEM_EULER: SurfFlow_file << "\"Mach_Number\"" << "\n"; break;
710  case NAVIER_STOKES: case RANS: case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES:
711  if (nDim == 2) SurfFlow_file << "\"Skin_Friction_Coefficient_X\", \"Skin_Friction_Coefficient_Y\", \"Heat_Flux\"" << "\n";
712  if (nDim == 3) SurfFlow_file << "\"Skin_Friction_Coefficient_X\", \"Skin_Friction_Coefficient_Y\", \"Skin_Friction_Coefficient_Z\", \"Heat_Flux\"" << "\n";
713  break;
714  }
715 
716  /*--- Loop through all of the collected data and write each node's values ---*/
717 
718  unsigned long Total_Index;
719  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
720  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) {
721 
722  /*--- Current index position and global index ---*/
723  Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex;
724  Global_Index = Buffer_Recv_GlobalIndex[Total_Index];
725 
726  /*--- Retrieve the merged data for this node ---*/
727  xCoord = Buffer_Recv_Coord_x[Total_Index];
728  yCoord = Buffer_Recv_Coord_y[Total_Index];
729  if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index];
730  Pressure = Buffer_Recv_Press[Total_Index];
731  PressCoeff = Buffer_Recv_CPress[Total_Index];
732 
733  /*--- Write the first part of the data ---*/
734  SurfFlow_file << scientific << Global_Index << ", " << xCoord << ", " << yCoord << ", ";
735  if (nDim == 3) SurfFlow_file << scientific << zCoord << ", ";
736  SurfFlow_file << scientific << Pressure << ", " << PressCoeff << ", ";
737 
738  /*--- Write the solver-dependent part of the data ---*/
739  switch (solver) {
740  case EULER :
741  case FEM_EULER:
742  Mach = Buffer_Recv_Mach[Total_Index];
743  SurfFlow_file << scientific << Mach << "\n";
744  break;
745  case NAVIER_STOKES: case RANS:
746  case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES:
747  SkinFrictionCoeff[0] = Buffer_Recv_SkinFriction_x[Total_Index];
748  SkinFrictionCoeff[1] = Buffer_Recv_SkinFriction_y[Total_Index];
749  if (nDim == 3) SkinFrictionCoeff[2] = Buffer_Recv_SkinFriction_z[Total_Index];
750  HeatFlux = Buffer_Recv_HeatTransfer[Total_Index];
751  if (nDim == 2) SurfFlow_file << scientific << SkinFrictionCoeff[0] << ", " << SkinFrictionCoeff[1] << ", " << HeatFlux << "\n";
752  if (nDim == 3) SurfFlow_file << scientific << SkinFrictionCoeff[0] << ", " << SkinFrictionCoeff[1] << ", " << SkinFrictionCoeff[2] << ", " << HeatFlux << "\n";
753  break;
754  }
755  }
756  }
757 
758  /*--- Close the CSV file ---*/
759  SurfFlow_file.close();
760 
761  /*--- Release the recv buffers on the master node ---*/
762 
763  delete [] Buffer_Recv_Coord_x;
764  delete [] Buffer_Recv_Coord_y;
765  if (nDim == 3) delete [] Buffer_Recv_Coord_z;
766  delete [] Buffer_Recv_Press;
767  delete [] Buffer_Recv_CPress;
768  delete [] Buffer_Recv_Mach;
769  delete [] Buffer_Recv_SkinFriction_x;
770  delete [] Buffer_Recv_SkinFriction_y;
771  if (nDim == 3) delete [] Buffer_Recv_SkinFriction_z;
772  delete [] Buffer_Recv_HeatTransfer;
773  delete [] Buffer_Recv_GlobalIndex;
774 
775  delete [] Buffer_Recv_nVertex;
776 
777  }
778 
779  /*--- Release the memory for the remaining buffers and exit ---*/
780 
781  delete [] Buffer_Send_Coord_x;
782  delete [] Buffer_Send_Coord_y;
783  delete [] Buffer_Send_Coord_z;
784  delete [] Buffer_Send_Press;
785  delete [] Buffer_Send_CPress;
786  delete [] Buffer_Send_Mach;
787  delete [] Buffer_Send_SkinFriction_x;
788  delete [] Buffer_Send_SkinFriction_y;
789  delete [] Buffer_Send_SkinFriction_z;
790  delete [] Buffer_Send_HeatTransfer;
791  delete [] Buffer_Send_GlobalIndex;
792 
793 #endif
794 
795 }
796 
797 void COutput::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, CSolver *AdjSolver, CSolver *FlowSolution, unsigned long iExtIter, unsigned short val_iZone, unsigned short val_iInst) {
798 
799 #ifndef HAVE_MPI
800 
801  unsigned long iPoint, iVertex, Global_Index;
802  su2double *Solution, xCoord, yCoord, zCoord;
803  unsigned short iMarker;
804  char cstr[200], buffer[50];
805  ofstream SurfAdj_file;
806 
807  bool transp = (config->GetnMarker_Transpiration() > 0);
808 
809  /*--- Write file name with extension if unsteady ---*/
810 
811  strcpy (cstr, config->GetSurfAdjCoeff_FileName().c_str());
812 
813  if (config->GetUnsteady_Simulation() == HARMONIC_BALANCE) {
814  SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(val_iInst));
815 
816  } else if (config->GetUnsteady_Simulation() && config->GetWrt_Unsteady()) {
817  if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.csv", SU2_TYPE::Int(iExtIter));
818  if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d.csv", SU2_TYPE::Int(iExtIter));
819  if ((SU2_TYPE::Int(iExtIter) >= 100) && (SU2_TYPE::Int(iExtIter) < 1000)) SPRINTF (buffer, "_00%d.csv", SU2_TYPE::Int(iExtIter));
820  if ((SU2_TYPE::Int(iExtIter) >= 1000) && (SU2_TYPE::Int(iExtIter) < 10000)) SPRINTF (buffer, "_0%d.csv", SU2_TYPE::Int(iExtIter));
821  if (SU2_TYPE::Int(iExtIter) >= 10000) SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(iExtIter));
822  }
823  else
824  SPRINTF (buffer, ".csv");
825 
826  strcat(cstr, buffer);
827  SurfAdj_file.precision(15);
828  SurfAdj_file.open(cstr, ios::out);
829 
830  SurfAdj_file << "SENS_AOA=" << AdjSolver->GetTotal_Sens_AoA() * PI_NUMBER / 180.0 << endl;
831 
832  if (geometry->GetnDim() == 2) {
833  if (config ->GetKind_Regime() == COMPRESSIBLE)
834  SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"PsiE\",\"x_coord\",\"y_coord\"";
835  else if (config ->GetKind_Regime() == INCOMPRESSIBLE)
836  SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"x_coord\",\"y_coord\"";
837 
838  if (config->GetDiscrete_Adjoint()) {
839  SurfAdj_file << ",\"x_Sens\",\"y_Sens\"";
840  if(transp)
841  SurfAdj_file << ",\"Sens_Transp\"";
842  }
843  SurfAdj_file << "\n";
844 
845  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
846  if (config->GetMarker_All_Plotting(iMarker) == YES)
847  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
848  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
849  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
850  Solution = AdjSolver->node[iPoint]->GetSolution();
851  xCoord = geometry->node[iPoint]->GetCoord(0);
852  yCoord = geometry->node[iPoint]->GetCoord(1);
853 
854  /*--- If US system, the output should be in inches ---*/
855 
856  if (config->GetSystemMeasurements() == US) {
857  xCoord *= 12.0;
858  yCoord *= 12.0;
859  }
860  if (config ->GetKind_Regime() == COMPRESSIBLE)
861  SurfAdj_file << scientific << Global_Index << ", " << AdjSolver->GetCSensitivity(iMarker, iVertex) << ", " << Solution[0] << ", "
862  << Solution[1] << ", " << Solution[2] << ", " << Solution[3] <<", " << xCoord <<", "<< yCoord;
863  else if (config ->GetKind_Regime() == INCOMPRESSIBLE)
864  SurfAdj_file << scientific << Global_Index << ", " << AdjSolver->GetCSensitivity(iMarker, iVertex) << ", " << Solution[0] << ", "
865  << Solution[1] << ", " << Solution[2] <<", " << xCoord <<", "<< yCoord;
866  if (config->GetDiscrete_Adjoint()) {
867  SurfAdj_file << ", " << AdjSolver->node[iPoint]->GetSensitivity(0) << ", " << AdjSolver->node[iPoint]->GetSensitivity(1);
868  if(transp)
869  SurfAdj_file << ", " << AdjSolver->node[iPoint]->GetSensitivityTranspiration();
870  }
871  SurfAdj_file << "\n";
872  }
873  }
874  }
875 
876  if (geometry->GetnDim() == 3) {
877  if (config ->GetKind_Regime() == COMPRESSIBLE)
878  SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"Phi_z\",\"PsiE\",\"x_coord\",\"y_coord\",\"z_coord\"";
879  else if (config ->GetKind_Regime() == INCOMPRESSIBLE)
880  SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"Phi_z\",\"x_coord\",\"y_coord\",\"z_coord\"";
881 
882  if (config->GetDiscrete_Adjoint()) {
883  SurfAdj_file << ",\"x_Sens\",\"y_Sens\",\"z_Sens\"";
884  if(transp)
885  SurfAdj_file << ",\"Sens_Transp\"";
886  }
887  SurfAdj_file << "\n";
888  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
889  if (config->GetMarker_All_Plotting(iMarker) == YES)
890  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
891  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
892  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
893  Solution = AdjSolver->node[iPoint]->GetSolution();
894 
895  xCoord = geometry->node[iPoint]->GetCoord(0);
896  yCoord = geometry->node[iPoint]->GetCoord(1);
897  zCoord = geometry->node[iPoint]->GetCoord(2);
898 
899  /*--- If US system, the output should be in inches ---*/
900 
901  if (config->GetSystemMeasurements() == US) {
902  xCoord *= 12.0;
903  yCoord *= 12.0;
904  zCoord *= 12.0;
905  }
906  if (config ->GetKind_Regime() == COMPRESSIBLE)
907  SurfAdj_file << scientific << Global_Index << ", " << AdjSolver->GetCSensitivity(iMarker, iVertex) << ", " << Solution[0] << ", "
908  << Solution[1] << ", " << Solution[2] << ", " << Solution[3] << ", " << Solution[4] << ", "<< xCoord <<", "<< yCoord <<", "<< zCoord;
909  else if (config ->GetKind_Regime() == INCOMPRESSIBLE)
910  SurfAdj_file << scientific << Global_Index << ", " << AdjSolver->GetCSensitivity(iMarker, iVertex) << ", " << Solution[0] << ", "
911  << Solution[1] << ", " << Solution[2] << ", " << Solution[3] << ", " << xCoord <<", "<< yCoord <<", "<< zCoord;
912  if (config->GetDiscrete_Adjoint()) {
913  SurfAdj_file << ", " << AdjSolver->node[iPoint]->GetSensitivity(0) << ", " << AdjSolver->node[iPoint]->GetSensitivity(1)
914  << ", " << AdjSolver->node[iPoint]->GetSensitivity(2);
915  if(transp)
916  SurfAdj_file << ", " << AdjSolver->node[iPoint]->GetSensitivityTranspiration();
917  }
918  SurfAdj_file << "\n";
919  }
920  }
921  }
922 
923  SurfAdj_file.close();
924 
925 #else
926  int iProcessor, nProcessor = size;
927 
928  unsigned short nDim = geometry->GetnDim(), iMarker;
929  su2double *Solution, *Coord;
930  unsigned long Buffer_Send_nVertex[1], iVertex, iPoint, nVertex_Surface = 0, nLocalVertex_Surface = 0,
931  MaxLocalVertex_Surface = 0, nBuffer_Scalar;
932  unsigned long *Buffer_Receive_nVertex = NULL;
933  ofstream SurfAdj_file;
934 
935  bool transp = (config->GetnMarker_Transpiration() > 0);
936 
937  /*--- Write the surface .csv file ---*/
938  nLocalVertex_Surface = 0;
939  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
940  if (config->GetMarker_All_Plotting(iMarker) == YES)
941  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
942  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
943  if (geometry->node[iPoint]->GetDomain()) nLocalVertex_Surface ++;
944  }
945 
946  if (rank == MASTER_NODE)
947  Buffer_Receive_nVertex = new unsigned long [nProcessor];
948 
949  Buffer_Send_nVertex[0] = nLocalVertex_Surface;
950 
951  SU2_MPI::Allreduce(&nLocalVertex_Surface, &MaxLocalVertex_Surface, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
952  SU2_MPI::Gather(&Buffer_Send_nVertex, 1, MPI_UNSIGNED_LONG, Buffer_Receive_nVertex, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
953 
954  su2double *Buffer_Send_Coord_x = new su2double[MaxLocalVertex_Surface];
955  su2double *Buffer_Send_Coord_y= new su2double[MaxLocalVertex_Surface];
956  su2double *Buffer_Send_Coord_z= new su2double[MaxLocalVertex_Surface];
957  unsigned long *Buffer_Send_GlobalPoint= new unsigned long[MaxLocalVertex_Surface];
958  su2double *Buffer_Send_Sensitivity= new su2double[MaxLocalVertex_Surface];
959  su2double *Buffer_Send_PsiRho= new su2double[MaxLocalVertex_Surface];
960  su2double *Buffer_Send_Phi_x= new su2double[MaxLocalVertex_Surface];
961  su2double *Buffer_Send_Phi_y= new su2double[MaxLocalVertex_Surface];
962  su2double *Buffer_Send_Phi_z= new su2double[MaxLocalVertex_Surface];
963  su2double *Buffer_Send_PsiE = NULL;
964 
965  if (config ->GetKind_Regime() == COMPRESSIBLE)
966  Buffer_Send_PsiE = new su2double[MaxLocalVertex_Surface];
967 
968  su2double *Buffer_Send_Sens_x = NULL, *Buffer_Send_Sens_y = NULL, *Buffer_Send_Sens_z = NULL;
969  su2double *Buffer_Send_Sens_Transp = NULL;
970 
971  if (config->GetDiscrete_Adjoint()) {
972  Buffer_Send_Sens_x = new su2double[MaxLocalVertex_Surface];
973  Buffer_Send_Sens_y = new su2double[MaxLocalVertex_Surface];
974  if (nDim == 3) {
975  Buffer_Send_Sens_z = new su2double[MaxLocalVertex_Surface];
976  }
977  if(transp){
978  Buffer_Send_Sens_Transp = new su2double[MaxLocalVertex_Surface];
979  }
980  }
981 
982  nVertex_Surface = 0;
983  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
984  if (config->GetMarker_All_Plotting(iMarker) == YES)
985  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
986  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
987  if (geometry->node[iPoint]->GetDomain()) {
988  Solution = AdjSolver->node[iPoint]->GetSolution();
989  //Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
990  Coord = geometry->node[iPoint]->GetCoord();
991  //d = AdjSolver->node[iPoint]->GetForceProj_Vector();
992  Buffer_Send_GlobalPoint[nVertex_Surface] = geometry->node[iPoint]->GetGlobalIndex();
993  Buffer_Send_Coord_x[nVertex_Surface] = Coord[0];
994  Buffer_Send_Coord_y[nVertex_Surface] = Coord[1];
995  Buffer_Send_Sensitivity[nVertex_Surface] = AdjSolver->GetCSensitivity(iMarker, iVertex);
996  Buffer_Send_PsiRho[nVertex_Surface] = Solution[0];
997  Buffer_Send_Phi_x[nVertex_Surface] = Solution[1];
998  Buffer_Send_Phi_y[nVertex_Surface] = Solution[2];
999  if ((nDim == 2) && (config->GetKind_Regime() == COMPRESSIBLE)) Buffer_Send_PsiE[nVertex_Surface] = Solution[3];
1000  if (nDim == 3) {
1001  Buffer_Send_Coord_z[nVertex_Surface] = Coord[2];
1002  Buffer_Send_Phi_z[nVertex_Surface] = Solution[3];
1003  if(config->GetKind_Regime() == COMPRESSIBLE) Buffer_Send_PsiE[nVertex_Surface] = Solution[4];
1004  }
1005  if (config->GetDiscrete_Adjoint()) {
1006  Buffer_Send_Sens_x[nVertex_Surface] = AdjSolver->node[iPoint]->GetSensitivity(0);
1007  Buffer_Send_Sens_y[nVertex_Surface] = AdjSolver->node[iPoint]->GetSensitivity(1);
1008  if (nDim == 3) {
1009  Buffer_Send_Sens_z[nVertex_Surface] = AdjSolver->node[iPoint]->GetSensitivity(2);
1010  }
1011  if(transp){
1012  Buffer_Send_Sens_Transp[nVertex_Surface] = AdjSolver->node[iPoint]->GetSensitivityTranspiration();
1013  }
1014  }
1015 
1016  /*--- If US system, the output should be in inches ---*/
1017 
1018  if (config->GetSystemMeasurements() == US) {
1019  Buffer_Send_Coord_x[nVertex_Surface] *= 12.0;
1020  Buffer_Send_Coord_y[nVertex_Surface] *= 12.0;
1021  if (nDim == 3) Buffer_Send_Coord_z[nVertex_Surface] *= 12.0;
1022  }
1023 
1024  nVertex_Surface++;
1025  }
1026  }
1027 
1028  su2double *Buffer_Receive_Coord_x = NULL, *Buffer_Receive_Coord_y = NULL, *Buffer_Receive_Coord_z = NULL, *Buffer_Receive_Sensitivity = NULL,
1029  *Buffer_Receive_PsiRho = NULL, *Buffer_Receive_Phi_x = NULL, *Buffer_Receive_Phi_y = NULL, *Buffer_Receive_Phi_z = NULL,
1030  *Buffer_Receive_PsiE = NULL, *Buffer_Receive_Sens_x = NULL, *Buffer_Receive_Sens_y = NULL, *Buffer_Receive_Sens_z = NULL,
1031  *Buffer_Receive_Sens_Transp = NULL;
1032  unsigned long *Buffer_Receive_GlobalPoint = NULL;
1033 
1034  if (rank == MASTER_NODE) {
1035  Buffer_Receive_Coord_x = new su2double [nProcessor*MaxLocalVertex_Surface];
1036  Buffer_Receive_Coord_y = new su2double [nProcessor*MaxLocalVertex_Surface];
1037  if (nDim == 3) Buffer_Receive_Coord_z = new su2double [nProcessor*MaxLocalVertex_Surface];
1038  Buffer_Receive_GlobalPoint = new unsigned long [nProcessor*MaxLocalVertex_Surface];
1039  Buffer_Receive_Sensitivity = new su2double [nProcessor*MaxLocalVertex_Surface];
1040  Buffer_Receive_PsiRho = new su2double [nProcessor*MaxLocalVertex_Surface];
1041  Buffer_Receive_Phi_x = new su2double [nProcessor*MaxLocalVertex_Surface];
1042  Buffer_Receive_Phi_y = new su2double [nProcessor*MaxLocalVertex_Surface];
1043  if (nDim == 3) Buffer_Receive_Phi_z = new su2double [nProcessor*MaxLocalVertex_Surface];
1044  if (config->GetKind_Regime() == COMPRESSIBLE)
1045  Buffer_Receive_PsiE = new su2double [nProcessor*MaxLocalVertex_Surface];
1046  if (config->GetDiscrete_Adjoint()) {
1047  Buffer_Receive_Sens_x = new su2double[nProcessor*MaxLocalVertex_Surface];
1048  Buffer_Receive_Sens_y = new su2double[nProcessor*MaxLocalVertex_Surface];
1049  if (nDim == 3) {
1050  Buffer_Receive_Sens_z = new su2double[nProcessor*MaxLocalVertex_Surface];
1051  }
1052  if (transp) {
1053  Buffer_Receive_Sens_Transp = new su2double[nProcessor*MaxLocalVertex_Surface];
1054  }
1055  }
1056  }
1057 
1058  nBuffer_Scalar = MaxLocalVertex_Surface;
1059 
1060  /*--- Send the information to the Master node ---*/
1061  SU2_MPI::Gather(Buffer_Send_Coord_x, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Coord_x, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1062  SU2_MPI::Gather(Buffer_Send_Coord_y, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Coord_y, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1063  if (nDim == 3) SU2_MPI::Gather(Buffer_Send_Coord_z, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Coord_z, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1064  SU2_MPI::Gather(Buffer_Send_GlobalPoint, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Receive_GlobalPoint, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
1065  SU2_MPI::Gather(Buffer_Send_Sensitivity, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Sensitivity, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1066  SU2_MPI::Gather(Buffer_Send_PsiRho, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_PsiRho, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1067  SU2_MPI::Gather(Buffer_Send_Phi_x, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Phi_x, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1068  SU2_MPI::Gather(Buffer_Send_Phi_y, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Phi_y, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1069  if (nDim == 3) SU2_MPI::Gather(Buffer_Send_Phi_z, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Phi_z, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1070  if (config->GetKind_Regime() == COMPRESSIBLE)
1071  SU2_MPI::Gather(Buffer_Send_PsiE, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_PsiE, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1072  if (config->GetDiscrete_Adjoint()) {
1073  SU2_MPI::Gather(Buffer_Send_Sens_x, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Sens_x, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1074  SU2_MPI::Gather(Buffer_Send_Sens_y, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Sens_y, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1075  if (nDim == 3) {
1076  SU2_MPI::Gather(Buffer_Send_Sens_z, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Sens_z, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1077  }
1078  if (transp) {
1079  SU2_MPI::Gather(Buffer_Send_Sens_Transp, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Sens_Transp, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1080  }
1081  }
1082 
1083  /*--- The master node is the one who writes the surface files ---*/
1084  if (rank == MASTER_NODE) {
1085  unsigned long iVertex, GlobalPoint, position;
1086  char cstr[200], buffer[50];
1087  ofstream SurfAdj_file;
1088  string filename = config->GetSurfAdjCoeff_FileName();
1089 
1090  /*--- Write file name with extension if unsteady ---*/
1091  strcpy (cstr, filename.c_str());
1092 
1093  if (config->GetUnsteady_Simulation() == HARMONIC_BALANCE) {
1094  SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(val_iInst));
1095 
1096  } else if (config->GetUnsteady_Simulation() && config->GetWrt_Unsteady()) {
1097  if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.csv", SU2_TYPE::Int(iExtIter));
1098  if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d.csv", SU2_TYPE::Int(iExtIter));
1099  if ((SU2_TYPE::Int(iExtIter) >= 100) && (SU2_TYPE::Int(iExtIter) < 1000)) SPRINTF (buffer, "_00%d.csv", SU2_TYPE::Int(iExtIter));
1100  if ((SU2_TYPE::Int(iExtIter) >= 1000) && (SU2_TYPE::Int(iExtIter) < 10000)) SPRINTF (buffer, "_0%d.csv", SU2_TYPE::Int(iExtIter));
1101  if (SU2_TYPE::Int(iExtIter) >= 10000) SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(iExtIter));
1102  }
1103  else
1104  SPRINTF (buffer, ".csv");
1105 
1106  strcat (cstr, buffer);
1107  SurfAdj_file.open(cstr, ios::out);
1108  SurfAdj_file.precision(15);
1109 
1110  SurfAdj_file << "SENS_AOA=" << AdjSolver->GetTotal_Sens_AoA() * PI_NUMBER / 180.0 << endl;
1111 
1112  /*--- Write the 2D surface flow coefficient file ---*/
1113  if (geometry->GetnDim() == 2) {
1114  if (config->GetKind_Regime() == COMPRESSIBLE)
1115  SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"PsiE\",\"x_coord\",\"y_coord\"";
1116  else if (config->GetKind_Regime() == INCOMPRESSIBLE)
1117  SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"x_coord\",\"y_coord\"";
1118 
1119  if (config->GetDiscrete_Adjoint()) {
1120  SurfAdj_file << ",\" x_Sens\",\"y_Sens\"";
1121  if(transp)
1122  SurfAdj_file << ",\"Sens_Transp\"";
1123  }
1124  SurfAdj_file << "\n";
1125 
1126  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++)
1127  for (iVertex = 0; iVertex < Buffer_Receive_nVertex[iProcessor]; iVertex++) {
1128 
1129  position = iProcessor*MaxLocalVertex_Surface+iVertex;
1130  GlobalPoint = Buffer_Receive_GlobalPoint[position];
1131 
1132  if (config->GetKind_Regime() == COMPRESSIBLE)
1133  SurfAdj_file << scientific << GlobalPoint <<
1134  ", " << Buffer_Receive_Sensitivity[position] << ", " << Buffer_Receive_PsiRho[position] <<
1135  ", " << Buffer_Receive_Phi_x[position] << ", " << Buffer_Receive_Phi_y[position] <<
1136  ", " << Buffer_Receive_PsiE[position] << ", " << Buffer_Receive_Coord_x[position] <<
1137  ", "<< Buffer_Receive_Coord_y[position];
1138  else if (config->GetKind_Regime() == INCOMPRESSIBLE)
1139  SurfAdj_file << scientific << GlobalPoint <<
1140  ", " << Buffer_Receive_Sensitivity[position] << ", " << Buffer_Receive_PsiRho[position] <<
1141  ", " << Buffer_Receive_Phi_x[position] << ", " << Buffer_Receive_Phi_y[position] <<
1142  ", " << Buffer_Receive_Coord_x[position] <<
1143  ", "<< Buffer_Receive_Coord_y[position];
1144  if (config->GetDiscrete_Adjoint()) {
1145  SurfAdj_file << ", " << Buffer_Receive_Sens_x[position] << ", " << Buffer_Receive_Sens_y[position];
1146  if(transp){
1147  SurfAdj_file << ", " << Buffer_Receive_Sens_Transp[position];
1148  }
1149  }
1150  SurfAdj_file << "\n";
1151  }
1152  }
1153 
1154  /*--- Write the 3D surface flow coefficient file ---*/
1155  if (geometry->GetnDim() == 3) {
1156  if (config->GetKind_Regime() == COMPRESSIBLE)
1157  SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"Phi_z\",\"PsiE\",\"x_coord\",\"y_coord\",\"z_coord\"";
1158  else if (config->GetKind_Regime() == INCOMPRESSIBLE)
1159  SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"Phi_z\",\"x_coord\",\"y_coord\",\"z_coord\"";
1160 
1161  if (config->GetDiscrete_Adjoint()) {
1162  SurfAdj_file << ",\"x_Sens\",\"y_Sens\",\"z_Sens\"";
1163  if(transp)
1164  SurfAdj_file << ",\"Sens_Transp\"";
1165  }
1166  SurfAdj_file << "\n";
1167 
1168  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++)
1169  for (iVertex = 0; iVertex < Buffer_Receive_nVertex[iProcessor]; iVertex++) {
1170  position = iProcessor*MaxLocalVertex_Surface+iVertex;
1171  GlobalPoint = Buffer_Receive_GlobalPoint[position];
1172 
1173  if (config->GetKind_Regime() == COMPRESSIBLE)
1174  SurfAdj_file << scientific << GlobalPoint <<
1175  ", " << Buffer_Receive_Sensitivity[position] << ", " << Buffer_Receive_PsiRho[position] <<
1176  ", " << Buffer_Receive_Phi_x[position] << ", " << Buffer_Receive_Phi_y[position] << ", " << Buffer_Receive_Phi_z[position] <<
1177  ", " << Buffer_Receive_PsiE[position] <<", "<< Buffer_Receive_Coord_x[position] <<
1178  ", "<< Buffer_Receive_Coord_y[position] <<", "<< Buffer_Receive_Coord_z[position];
1179  else if (config->GetKind_Regime() == INCOMPRESSIBLE)
1180  SurfAdj_file << scientific << GlobalPoint <<
1181  ", " << Buffer_Receive_Sensitivity[position] << ", " << Buffer_Receive_PsiRho[position] <<
1182  ", " << Buffer_Receive_Phi_x[position] << ", " << Buffer_Receive_Phi_y[position] << ", " << Buffer_Receive_Phi_z[position] <<
1183  ", "<< Buffer_Receive_Coord_x[position] <<
1184  ", "<< Buffer_Receive_Coord_y[position] <<", "<< Buffer_Receive_Coord_z[position];
1185 
1186  if (config->GetDiscrete_Adjoint()) {
1187  SurfAdj_file << ", " << Buffer_Receive_Sens_x[position] << ", " << Buffer_Receive_Sens_y[position] << ", " << Buffer_Receive_Sens_z[position];
1188  if(transp){
1189  SurfAdj_file << ", " << Buffer_Receive_Sens_Transp[position];
1190  }
1191  }
1192  SurfAdj_file << "\n";
1193  }
1194  }
1195 
1196  }
1197 
1198  if (rank == MASTER_NODE) {
1199  delete [] Buffer_Receive_nVertex;
1200  delete [] Buffer_Receive_Coord_x;
1201  delete [] Buffer_Receive_Coord_y;
1202  if (nDim == 3) delete [] Buffer_Receive_Coord_z;
1203  delete [] Buffer_Receive_Sensitivity;
1204  delete [] Buffer_Receive_PsiRho;
1205  delete [] Buffer_Receive_Phi_x;
1206  delete [] Buffer_Receive_Phi_y;
1207  if (nDim == 3) delete [] Buffer_Receive_Phi_z;
1208  if (config->GetKind_Regime() == COMPRESSIBLE)
1209  delete [] Buffer_Receive_PsiE;
1210  delete [] Buffer_Receive_GlobalPoint;
1211  if (config->GetDiscrete_Adjoint()) {
1212  delete [] Buffer_Receive_Sens_x;
1213  delete [] Buffer_Receive_Sens_y;
1214  if (nDim == 3) {
1215  delete [] Buffer_Receive_Sens_z;
1216  }
1217  if (transp) {
1218  delete [] Buffer_Receive_Sens_Transp;
1219  }
1220  }
1221  }
1222 
1223  delete [] Buffer_Send_Coord_x;
1224  delete [] Buffer_Send_Coord_y;
1225  delete [] Buffer_Send_Coord_z;
1226  delete [] Buffer_Send_GlobalPoint;
1227  delete [] Buffer_Send_Sensitivity;
1228  delete [] Buffer_Send_PsiRho;
1229  delete [] Buffer_Send_Phi_x;
1230  delete [] Buffer_Send_Phi_y;
1231  delete [] Buffer_Send_Phi_z;
1232  delete [] Buffer_Send_PsiE;
1233  if (Buffer_Send_Sens_x != NULL) delete [] Buffer_Send_Sens_x;
1234  if (Buffer_Send_Sens_y != NULL) delete [] Buffer_Send_Sens_y;
1235  if (Buffer_Send_Sens_z != NULL) delete [] Buffer_Send_Sens_z;
1236  if (Buffer_Send_Sens_Transp != NULL) delete [] Buffer_Send_Sens_Transp;
1237 
1238  SurfAdj_file.close();
1239 
1240 #endif
1241 }
1242 
1243 void COutput::MergeConnectivity(CConfig *config, CGeometry *geometry, unsigned short val_iZone) {
1244 
1245  /*--- Flags identifying the types of files to be written. ---*/
1246 
1247  bool Wrt_Vol = config->GetWrt_Vol_Sol();
1248  bool Wrt_Srf = config->GetWrt_Srf_Sol();
1249 
1250  /*--- Merge connectivity for each type of element (excluding halos). Note
1251  that we only need to merge the connectivity once, as it does not change
1252  during computation. Check whether the base file has been written. ---*/
1253 
1254  /*--- Merge volumetric grid. ---*/
1255 
1256  if (Wrt_Vol) {
1257 
1258  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Tria != 0))
1259  cout <<"Merging volumetric triangle grid connectivity." << endl;
1260  MergeVolumetricConnectivity(config, geometry, TRIANGLE );
1261 
1262  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Quad != 0))
1263  cout <<"Merging volumetric quadrilateral grid connectivity." << endl;
1264  MergeVolumetricConnectivity(config, geometry, QUADRILATERAL );
1265 
1266  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Tetr != 0))
1267  cout <<"Merging volumetric tetrahedron grid connectivity." << endl;
1268  MergeVolumetricConnectivity(config, geometry, TETRAHEDRON );
1269 
1270  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Hexa != 0))
1271  cout <<"Merging volumetric hexahedron grid connectivity." << endl;
1272  MergeVolumetricConnectivity(config, geometry, HEXAHEDRON );
1273 
1274  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Pris != 0))
1275  cout <<"Merging volumetric prism grid connectivity." << endl;
1276  MergeVolumetricConnectivity(config, geometry, PRISM );
1277 
1278  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Pyra != 0))
1279  cout <<"Merging volumetric pyramid grid connectivity." << endl;
1280  MergeVolumetricConnectivity(config, geometry, PYRAMID );
1281 
1282  }
1283 
1284  /*--- Merge surface grid. ---*/
1285 
1286  if (Wrt_Srf) {
1287 
1288  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Line != 0))
1289  cout <<"Merging surface line grid connectivity." << endl;
1290  MergeSurfaceConnectivity(config, geometry, LINE);
1291 
1292  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_BoundTria != 0))
1293  cout <<"Merging surface triangle grid connectivity." << endl;
1294  MergeSurfaceConnectivity(config, geometry, TRIANGLE);
1295 
1296  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_BoundQuad != 0))
1297  cout <<"Merging surface quadrilateral grid connectivity." << endl;
1298  MergeSurfaceConnectivity(config, geometry, QUADRILATERAL);
1299 
1300  }
1301 
1302  /*--- Update total number of volume elements after merge. ---*/
1303 
1304  nGlobal_Elem = nGlobal_Tria + nGlobal_Quad + nGlobal_Tetr +
1305  nGlobal_Hexa + nGlobal_Pyra + nGlobal_Pris;
1306 
1307  /*--- Update total number of surface elements after merge. ---*/
1308 
1309  nSurf_Elem = nGlobal_Line + nGlobal_BoundTria + nGlobal_BoundQuad;
1310 
1311 }
1312 
1313 void COutput::MergeCoordinates(CConfig *config, CGeometry *geometry) {
1314 
1315  /*--- Local variables needed on all processors ---*/
1316 
1317  unsigned short iDim, nDim = geometry->GetnDim();
1318  unsigned long iPoint;
1319 
1320  unsigned short kind_SU2 = config->GetKind_SU2();
1321 
1322 #ifndef HAVE_MPI
1323 
1324  /*--- In serial, the single process has access to all geometry, so simply
1325  load the coordinates into the data structure. ---*/
1326 
1327  unsigned short iMarker;
1328  unsigned long iVertex, nTotalPoints = 0;
1329  int SendRecv;
1330 
1331  bool isPeriodic;
1332 
1333  /*--- First, create a structure to locate any periodic halo nodes ---*/
1334  int *Local_Halo = new int[geometry->GetnPoint()];
1335  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
1336  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
1337 
1338  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
1339  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
1340  SendRecv = config->GetMarker_All_SendRecv(iMarker);
1341  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
1342  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
1343 
1344  /*--- For SU2_CFD and SU2_SOL we want to remove the periodic halo nodes,
1345  * but for SU2_DEF we want them to be included, therefore the definition of a periodic point
1346  * is different in each case ---*/
1347 
1348  if (kind_SU2 == SU2_DEF) {
1349  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0));
1350  }else {
1351  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
1352  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
1353  }
1354 
1355  if (isPeriodic && (SendRecv < 0)) {
1356  Local_Halo[iPoint] = false;
1357  }
1358  }
1359 
1360  }
1361  }
1362 
1363  /*--- Total number of points in the mesh (this might include periodic points). ---*/
1364  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
1365  if (!Local_Halo[iPoint]) nTotalPoints++;
1366 
1367  nGlobal_Poin = nTotalPoints;
1368  nGlobal_Doma = geometry->GetnPointDomain();
1369 
1370  /*--- Allocate the coordinates data structure. ---*/
1371 
1372  Coords = new su2double*[nDim];
1373  for (iDim = 0; iDim < nDim; iDim++) {
1374  Coords[iDim] = new su2double[nGlobal_Poin];
1375  }
1376 
1377  /*--- Loop over the mesh to collect the coords of the local points ---*/
1378 
1379  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
1380 
1381  /*--- Check if the node belongs to the domain (i.e, not a halo node).
1382  Sort by the global index, even in serial there is a renumbering (e.g. RCM). ---*/
1383 
1384  if (!Local_Halo[iPoint]) {
1385 
1386  /*--- Retrieve the current coordinates at this node. ---*/
1387 
1388  unsigned long iGlobal_Index = geometry->node[iPoint]->GetGlobalIndex();
1389 
1390  for (iDim = 0; iDim < nDim; iDim++) {
1391  Coords[iDim][iGlobal_Index] = geometry->node[iPoint]->GetCoord(iDim);
1392 
1393  /*--- If US system, the output should be in inches ---*/
1394 
1395  if ((config->GetSystemMeasurements() == US) && (config->GetKind_SU2() != SU2_DEF)) {
1396  Coords[iDim][iGlobal_Index] *= 12.0;
1397  }
1398 
1399  }
1400 
1401  }
1402  }
1403 
1404 
1405  delete [] Local_Halo;
1406 
1407 #else
1408 
1409  /*--- MPI preprocessing ---*/
1410  int iProcessor, nProcessor = size;
1411  unsigned long jPoint;
1412 
1413  bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
1414 
1415  /*--- Local variables needed for merging the geometry with MPI. ---*/
1416 
1417  unsigned long iVertex, iMarker;
1418  unsigned long Buffer_Send_nPoin[1], *Buffer_Recv_nPoin = NULL;
1419  unsigned long nLocalPoint = 0, MaxLocalPoint = 0;
1420  unsigned long iGlobal_Index = 0, nBuffer_Scalar = 0;
1421 
1422  if (rank == MASTER_NODE) Buffer_Recv_nPoin = new unsigned long[nProcessor];
1423 
1424  int *Local_Halo = new int[geometry->GetnPoint()];
1425  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
1426  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
1427 
1428  /*--- Search all send/recv boundaries on this partition for any periodic
1429  nodes that were part of the original domain. We want to recover these
1430  for visualization purposes. ---*/
1431 
1432  if (Wrt_Halo) {
1433  nLocalPoint = geometry->GetnPoint();
1434  } else {
1435  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
1436  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
1437 
1438  /*--- Checking for less than or equal to the rank, because there may
1439  be some periodic halo nodes that send info to the same rank. ---*/
1440 
1441  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
1442  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
1443 
1444  /*--- For SU2_CFD and SU2_SOL we want to remove the periodic halo nodes,
1445  * but for SU2_DEF we want them to be included, therefore the definition of a periodic point
1446  * is different in each case ---*/
1447 
1448  if (kind_SU2 == SU2_DEF) {
1449  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0));
1450  }else {
1451  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
1452  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
1453  }
1454  if (isPeriodic) {
1455  Local_Halo[iPoint] = false;
1456  }
1457  }
1458  }
1459  }
1460 
1461  /*--- Sum total number of nodes that belong to the domain ---*/
1462 
1463  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
1464  if (Local_Halo[iPoint] == false)
1465  nLocalPoint++;
1466  }
1467  Buffer_Send_nPoin[0] = nLocalPoint;
1468 
1469  /*--- Communicate the total number of nodes on this domain. ---*/
1470 
1471  SU2_MPI::Gather(&Buffer_Send_nPoin, 1, MPI_UNSIGNED_LONG,
1472  Buffer_Recv_nPoin, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
1473  SU2_MPI::Allreduce(&nLocalPoint, &MaxLocalPoint, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
1474 
1475  if (rank == MASTER_NODE) {
1476  nGlobal_Doma = 0;
1477  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
1478  nGlobal_Doma += Buffer_Recv_nPoin[iProcessor];
1479  }
1480  }
1481  nBuffer_Scalar = MaxLocalPoint;
1482 
1483  /*--- Send and Recv buffers. ---*/
1484 
1485  su2double *Buffer_Send_X = new su2double[MaxLocalPoint];
1486  su2double *Buffer_Recv_X = NULL;
1487 
1488  su2double *Buffer_Send_Y = new su2double[MaxLocalPoint];
1489  su2double *Buffer_Recv_Y = NULL;
1490 
1491  su2double *Buffer_Send_Z = NULL, *Buffer_Recv_Z = NULL;
1492  if (nDim == 3) Buffer_Send_Z = new su2double[MaxLocalPoint];
1493 
1494  unsigned long *Buffer_Send_GlobalIndex = new unsigned long[MaxLocalPoint];
1495  unsigned long *Buffer_Recv_GlobalIndex = NULL;
1496 
1497  /*--- Prepare the receive buffers in the master node only. ---*/
1498 
1499  if (rank == MASTER_NODE) {
1500 
1501  Buffer_Recv_X = new su2double[nProcessor*MaxLocalPoint];
1502  Buffer_Recv_Y = new su2double[nProcessor*MaxLocalPoint];
1503  if (nDim == 3) Buffer_Recv_Z = new su2double[nProcessor*MaxLocalPoint];
1504  Buffer_Recv_GlobalIndex = new unsigned long[nProcessor*MaxLocalPoint];
1505 
1506  /*--- Sum total number of nodes to be written and allocate arrays ---*/
1507  nGlobal_Poin = 0;
1508  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
1509  nGlobal_Poin += Buffer_Recv_nPoin[iProcessor];
1510  }
1511  Coords = new su2double*[nDim];
1512  for (iDim = 0; iDim < nDim; iDim++) {
1513  Coords[iDim] = new su2double[nGlobal_Poin];
1514  }
1515  }
1516 
1517  /*--- Main communication routine. Loop over each coordinate and perform
1518  the MPI comm. Temporary 1-D buffers are used to send the coordinates at
1519  all nodes on each partition to the master node. These are then unpacked
1520  by the master and sorted by global index in one large n-dim. array. ---*/
1521 
1522  /*--- Loop over this partition to collect the coords of the local points. ---*/
1523  su2double *Coords_Local; jPoint = 0;
1524  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
1525 
1526  /*--- Check for halos and write only if requested ---*/
1527  if (!Local_Halo[iPoint] || Wrt_Halo) {
1528 
1529  /*--- Retrieve local coordinates at this node. ---*/
1530  Coords_Local = geometry->node[iPoint]->GetCoord();
1531 
1532  /*--- Load local coords into the temporary send buffer. ---*/
1533  Buffer_Send_X[jPoint] = Coords_Local[0];
1534  Buffer_Send_Y[jPoint] = Coords_Local[1];
1535  if (nDim == 3) Buffer_Send_Z[jPoint] = Coords_Local[2];
1536 
1537  /*--- If US system, the output should be in inches ---*/
1538 
1539  if ((config->GetSystemMeasurements() == US) && (config->GetKind_SU2() != SU2_DEF)) {
1540  Buffer_Send_X[jPoint] *= 12.0;
1541  Buffer_Send_Y[jPoint] *= 12.0;
1542  if (nDim == 3) Buffer_Send_Z[jPoint] *= 12.0;
1543  }
1544 
1545  /*--- Store the global index for this local node. ---*/
1546  Buffer_Send_GlobalIndex[jPoint] = geometry->node[iPoint]->GetGlobalIndex();
1547 
1548  /*--- Increment jPoint as the counter. We need this because iPoint
1549  may include halo nodes that we skip over during this loop. ---*/
1550  jPoint++;
1551  }
1552  }
1553 
1554  /*--- Gather the coordinate data on the master node using MPI. ---*/
1555 
1556  SU2_MPI::Gather(Buffer_Send_X, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_X, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1557  SU2_MPI::Gather(Buffer_Send_Y, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Y, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1558  if (nDim == 3) {
1559  SU2_MPI::Gather(Buffer_Send_Z, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Z, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
1560  }
1561  SU2_MPI::Gather(Buffer_Send_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
1562 
1563  /*--- The master node unpacks and sorts this variable by global index ---*/
1564 
1565  if (rank == MASTER_NODE) {
1566  jPoint = 0;
1567  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
1568  for (iPoint = 0; iPoint < Buffer_Recv_nPoin[iProcessor]; iPoint++) {
1569  /*--- Get global index, then loop over each variable and store ---*/
1570  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
1571  if (iGlobal_Index >= nGlobal_Poin) {
1572  cout << iGlobal_Index << " " << nGlobal_Poin << endl;
1573  }
1574  Coords[0][iGlobal_Index] = Buffer_Recv_X[jPoint];
1575  Coords[1][iGlobal_Index] = Buffer_Recv_Y[jPoint];
1576  if (nDim == 3) Coords[2][iGlobal_Index] = Buffer_Recv_Z[jPoint];
1577  jPoint++;
1578  }
1579  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
1580  jPoint = (iProcessor+1)*nBuffer_Scalar;
1581  }
1582  }
1583 
1584  /*--- Immediately release the temporary data buffers. ---*/
1585 
1586  delete [] Local_Halo;
1587  delete [] Buffer_Send_X;
1588  delete [] Buffer_Send_Y;
1589  if (Buffer_Send_Z != NULL) delete [] Buffer_Send_Z;
1590  delete [] Buffer_Send_GlobalIndex;
1591  if (rank == MASTER_NODE) {
1592  delete [] Buffer_Recv_X;
1593  delete [] Buffer_Recv_Y;
1594  if (Buffer_Recv_Z != NULL) delete [] Buffer_Recv_Z;
1595  delete [] Buffer_Recv_GlobalIndex;
1596  delete [] Buffer_Recv_nPoin;
1597  }
1598 
1599 #endif
1600 
1601 }
1602 
1603 void COutput::MergeVolumetricConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) {
1604 
1605  int iProcessor;
1606  unsigned short NODES_PER_ELEMENT = 0;
1607  unsigned long iPoint, iNode, jNode;
1608  unsigned long iElem = 0;
1609  unsigned long nLocalElem = 0, nElem_Total = 0;
1610 
1611  unsigned long iVertex, iMarker;
1612  unsigned long jElem;
1613  int SendRecv, RecvFrom;
1614 
1615  unsigned long Buffer_Send_nElem[1], *Buffer_Recv_nElem = NULL;
1616  unsigned long nBuffer_Scalar = 0;
1617  unsigned long kNode = 0, kElem = 0;
1618  unsigned long MaxLocalElem = 0, iGlobal_Index, jPoint, kPoint;
1619 
1620  bool Wrt_Halo = config->GetWrt_Halo();
1621  bool *Write_Elem = NULL, notPeriodic, notHalo, addedPeriodic, isPeriodic;
1622 
1623  unsigned short kind_SU2 = config->GetKind_SU2();
1624 
1625  int *Conn_Elem = NULL;
1626 
1627  /*--- Store the local number of this element type and the number of nodes
1628  per this element type. In serial, this will be the total number of this
1629  element type in the entire mesh. In parallel, it is the number on only
1630  the current partition. ---*/
1631 
1632  switch (Elem_Type) {
1633  case TRIANGLE:
1634  nLocalElem = geometry->GetnElemTria();
1635  NODES_PER_ELEMENT = N_POINTS_TRIANGLE;
1636  break;
1637  case QUADRILATERAL:
1638  nLocalElem = geometry->GetnElemQuad();
1639  NODES_PER_ELEMENT = N_POINTS_QUADRILATERAL;
1640  break;
1641  case TETRAHEDRON:
1642  nLocalElem = geometry->GetnElemTetr();
1643  NODES_PER_ELEMENT = N_POINTS_TETRAHEDRON;
1644  break;
1645  case HEXAHEDRON:
1646  nLocalElem = geometry->GetnElemHexa();
1647  NODES_PER_ELEMENT = N_POINTS_HEXAHEDRON;
1648  break;
1649  case PRISM:
1650  nLocalElem = geometry->GetnElemPris();
1651  NODES_PER_ELEMENT = N_POINTS_PRISM;
1652  break;
1653  case PYRAMID:
1654  nLocalElem = geometry->GetnElemPyra();
1655  NODES_PER_ELEMENT = N_POINTS_PYRAMID;
1656  break;
1657  default:
1658  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
1659  }
1660 
1661  /*--- Find the max number of this element type among all
1662  partitions and set up buffers. ---*/
1663 
1664  Buffer_Send_nElem[0] = nLocalElem;
1665  if (rank == MASTER_NODE) Buffer_Recv_nElem = new unsigned long[size];
1666 
1667 #ifdef HAVE_MPI
1668  SU2_MPI::Allreduce(&nLocalElem, &MaxLocalElem, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
1669  SU2_MPI::Gather(&Buffer_Send_nElem, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nElem, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
1670 #else
1671  MaxLocalElem = nLocalElem;
1672  Buffer_Recv_nElem[0] = Buffer_Send_nElem[0];
1673 #endif
1674 
1675  nBuffer_Scalar = MaxLocalElem*NODES_PER_ELEMENT;
1676 
1677  /*--- Send and Recv buffers ---*/
1678 
1679  unsigned long *Buffer_Send_Elem = new unsigned long[nBuffer_Scalar];
1680  unsigned long *Buffer_Recv_Elem = NULL;
1681 
1682  unsigned short *Buffer_Send_Halo = new unsigned short[MaxLocalElem];
1683  unsigned short *Buffer_Recv_Halo = NULL;
1684 
1685  /*--- Prepare the receive buffers on the master node only. ---*/
1686 
1687  if (rank == MASTER_NODE) {
1688  Buffer_Recv_Elem = new unsigned long[size*nBuffer_Scalar];
1689  Buffer_Recv_Halo = new unsigned short[size*MaxLocalElem];
1690  if (MaxLocalElem > 0) Conn_Elem = new int[size*MaxLocalElem*NODES_PER_ELEMENT];
1691  }
1692 
1693  /*--- Force the removal of all added periodic elements (use global index).
1694  First, we isolate and create a list of all added periodic points, excluding
1695  those that we part of the original domain (we want these to be in the
1696  output files). ---*/
1697 
1698  vector<unsigned long> Added_Periodic;
1699  Added_Periodic.clear();
1700 
1701  if (kind_SU2 != SU2_DEF) {
1702  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
1703  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
1704  SendRecv = config->GetMarker_All_SendRecv(iMarker);
1705  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
1706  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
1707 
1708  if ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
1709  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 0) &&
1710  (SendRecv < 0)) {
1711  Added_Periodic.push_back(geometry->node[iPoint]->GetGlobalIndex());
1712  }
1713  }
1714  }
1715  }
1716  }
1717 
1718  /*--- Now we communicate this information to all processors, so that they
1719  can force the removal of these particular nodes by flagging them as halo
1720  points. In general, this should be a small percentage of the total mesh,
1721  so the communication/storage costs here shouldn't be prohibitive. ---*/
1722 
1723  /*--- First communicate the number of points that each rank has found ---*/
1724  unsigned long nAddedPeriodic = 0, maxAddedPeriodic = 0;
1725  unsigned long Buffer_Send_nAddedPeriodic[1], *Buffer_Recv_nAddedPeriodic = NULL;
1726  Buffer_Recv_nAddedPeriodic = new unsigned long[size];
1727 
1728  nAddedPeriodic = Added_Periodic.size();
1729  Buffer_Send_nAddedPeriodic[0] = nAddedPeriodic;
1730 
1731 #ifdef HAVE_MPI
1732  SU2_MPI::Allreduce(&nAddedPeriodic, &maxAddedPeriodic, 1, MPI_UNSIGNED_LONG,
1734  SU2_MPI::Allgather(&Buffer_Send_nAddedPeriodic, 1, MPI_UNSIGNED_LONG,
1735  Buffer_Recv_nAddedPeriodic, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
1736 #else
1737  maxAddedPeriodic = nAddedPeriodic;
1738  Buffer_Recv_nAddedPeriodic[0] = Buffer_Send_nAddedPeriodic[0];
1739 #endif
1740 
1741  /*--- Communicate the global index values of all added periodic nodes. ---*/
1742  unsigned long *Buffer_Send_AddedPeriodic = new unsigned long[maxAddedPeriodic];
1743  unsigned long *Buffer_Recv_AddedPeriodic = new unsigned long[size*maxAddedPeriodic];
1744 
1745  for (iPoint = 0; iPoint < Added_Periodic.size(); iPoint++) {
1746  Buffer_Send_AddedPeriodic[iPoint] = Added_Periodic[iPoint];
1747  }
1748 
1749  /*--- Gather the element connectivity information. All processors will now
1750  have a copy of the global index values for all added periodic points. ---*/
1751 
1752 #ifdef HAVE_MPI
1753  SU2_MPI::Allgather(Buffer_Send_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
1754  Buffer_Recv_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
1755  MPI_COMM_WORLD);
1756 #else
1757  for (iPoint = 0; iPoint < maxAddedPeriodic; iPoint++) Buffer_Recv_AddedPeriodic[iPoint] = Buffer_Send_AddedPeriodic[iPoint];
1758 #endif
1759 
1760  /*--- Search all send/recv boundaries on this partition for halo cells. In
1761  particular, consider only the recv conditions (these are the true halo
1762  nodes). Check the ranks of the processors that are communicating and
1763  choose to keep only the halo cells from the higher rank processor. Here,
1764  we are also choosing to keep periodic nodes that were part of the original
1765  domain. We will check the communicated list of added periodic points. ---*/
1766 
1767  int *Local_Halo = new int[geometry->GetnPoint()];
1768  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
1769  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
1770 
1771  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
1772  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
1773  SendRecv = config->GetMarker_All_SendRecv(iMarker);
1774  RecvFrom = abs(SendRecv)-1;
1775 
1776  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
1777  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
1778  iGlobal_Index = geometry->node[iPoint]->GetGlobalIndex();
1779 
1780  /*--- We need to keep one copy of overlapping halo cells. ---*/
1781  notHalo = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() == 0) &&
1782  (SendRecv < 0) && (rank > RecvFrom));
1783 
1784  /*--- We want to keep the periodic nodes that were part of the original domain.
1785  For SU2_DEF we want to keep all periodic nodes. ---*/
1786 
1787  if (kind_SU2 == SU2_DEF) {
1788  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0));
1789  }else {
1790  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
1791  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
1792  }
1793 
1794  notPeriodic = (isPeriodic && (SendRecv < 0));
1795 
1796  /*--- Lastly, check that this isn't an added periodic point that
1797  we will forcibly remove. Use the communicated list of these points. ---*/
1798  addedPeriodic = false; kPoint = 0;
1799  for (iProcessor = 0; iProcessor < size; iProcessor++) {
1800  for (jPoint = 0; jPoint < Buffer_Recv_nAddedPeriodic[iProcessor]; jPoint++) {
1801  if (iGlobal_Index == Buffer_Recv_AddedPeriodic[kPoint+jPoint])
1802  addedPeriodic = true;
1803  }
1804  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
1805  kPoint = (iProcessor+1)*maxAddedPeriodic;
1806  }
1807 
1808  /*--- If we found either of these types of nodes, flag them to be kept. ---*/
1809  if ((notHalo || notPeriodic) && !addedPeriodic) {
1810  Local_Halo[iPoint] = false;
1811  }
1812  }
1813  }
1814  }
1815 
1816  /*--- Loop over all elements in this partition and load the
1817  elements of the current type into the buffer to be sent to
1818  the master node. ---*/
1819 
1820  jNode = 0; jElem = 0;
1821  for (iElem = 0; iElem < geometry->GetnElem(); iElem++) {
1822  if (geometry->elem[iElem]->GetVTK_Type() == Elem_Type) {
1823 
1824  /*--- Loop over all nodes in this element and load the
1825  connectivity into the send buffer. ---*/
1826 
1827  Buffer_Send_Halo[jElem] = false;
1828  for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) {
1829 
1830  /*--- Store the global index values directly. ---*/
1831 
1832  iPoint = geometry->elem[iElem]->GetNode(iNode);
1833  Buffer_Send_Elem[jNode] = geometry->node[iPoint]->GetGlobalIndex();
1834 
1835  /*--- Check if this is a halo node. If so, flag this element
1836  as a halo cell. We will use this later to sort and remove
1837  any duplicates from the connectivity list. ---*/
1838 
1839  if (Local_Halo[iPoint]) {
1840  Buffer_Send_Halo[jElem] = true;
1841  }
1842 
1843  /*--- Increment jNode as the counter. We need this because iElem
1844  may include other elements that we skip over during this loop. ---*/
1845 
1846  jNode++;
1847  }
1848  jElem++;
1849  }
1850  }
1851 
1852  /*--- Gather the element connectivity information. ---*/
1853 
1854 #ifdef HAVE_MPI
1855  SU2_MPI::Gather(Buffer_Send_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
1856  SU2_MPI::Gather(Buffer_Send_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, Buffer_Recv_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, MASTER_NODE, MPI_COMM_WORLD);
1857 #else
1858  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Elem[iPoint] = Buffer_Send_Elem[iPoint];
1859  for (iPoint = 0; iPoint < MaxLocalElem; iPoint++) Buffer_Recv_Halo[iPoint] = Buffer_Send_Halo[iPoint];
1860 #endif
1861 
1862  /*--- The master node unpacks and sorts the connectivity. ---*/
1863 
1864  if (rank == MASTER_NODE) {
1865 
1866  /*--- We need to remove any duplicate elements (halo cells) that
1867  exist on multiple partitions. Start by initializing all elements
1868  to the "write" state by using a boolean array. ---*/
1869 
1870  Write_Elem = new bool[size*MaxLocalElem];
1871  for (iElem = 0; iElem < size*MaxLocalElem; iElem++) {
1872  Write_Elem[iElem] = true;
1873  }
1874 
1875  /*--- Remove the rind layer from the solution only if requested ---*/
1876 
1877  if (!Wrt_Halo) {
1878 
1879  /*--- Loop for flagging duplicate elements so that they are not
1880  included in the final connectivity list. ---*/
1881 
1882  kElem = 0;
1883  for (iProcessor = 0; iProcessor < size; iProcessor++) {
1884  for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) {
1885 
1886  /*--- Check if this element was marked as a halo. ---*/
1887  if (Buffer_Recv_Halo[kElem+iElem])
1888  Write_Elem[kElem+iElem] = false;
1889 
1890  }
1891  kElem = (iProcessor+1)*MaxLocalElem;
1892  }
1893  }
1894 
1895  /*--- Store the unique connectivity list for this element type. ---*/
1896 
1897  jNode = 0; kNode = 0; jElem = 0; nElem_Total = 0;
1898  for (iProcessor = 0; iProcessor < size; iProcessor++) {
1899  for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) {
1900 
1901  /*--- Only write the elements that were flagged for it. ---*/
1902  if (Write_Elem[jElem+iElem]) {
1903 
1904  /*--- Increment total count for this element type ---*/
1905  nElem_Total++;
1906 
1907  /*--- Get global index, then loop over each variable and store.
1908  Note that we are adding one to the index value because CGNS/Tecplot
1909  use 1-based indexing.---*/
1910 
1911  for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) {
1912  Conn_Elem[kNode] = (int)Buffer_Recv_Elem[jNode+iElem*NODES_PER_ELEMENT+iNode] + 1;
1913  kNode++;
1914  }
1915  }
1916  }
1917  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
1918  jElem = (iProcessor+1)*MaxLocalElem;
1919  jNode = (iProcessor+1)*nBuffer_Scalar;
1920  }
1921  }
1922 
1923  /*--- Immediately release the temporary buffers. ---*/
1924  delete [] Buffer_Send_Elem;
1925  delete [] Buffer_Send_Halo;
1926  delete [] Buffer_Recv_nAddedPeriodic;
1927  delete [] Buffer_Send_AddedPeriodic;
1928  delete [] Buffer_Recv_AddedPeriodic;
1929  delete [] Local_Halo;
1930  if (rank == MASTER_NODE) {
1931  delete [] Buffer_Recv_nElem;
1932  delete [] Buffer_Recv_Elem;
1933  delete [] Buffer_Recv_Halo;
1934  delete [] Write_Elem;
1935  }
1936 
1937  /*--- Store the particular global element count in the class data,
1938  and set the class data pointer to the connectivity array. ---*/
1939 
1940  if (rank == MASTER_NODE) {
1941  switch (Elem_Type) {
1942  case TRIANGLE:
1943  nGlobal_Tria = nElem_Total;
1944  if (nGlobal_Tria > 0) Conn_Tria = Conn_Elem;
1945  break;
1946  case QUADRILATERAL:
1947  nGlobal_Quad = nElem_Total;
1948  if (nGlobal_Quad > 0) Conn_Quad = Conn_Elem;
1949  break;
1950  case TETRAHEDRON:
1951  nGlobal_Tetr = nElem_Total;
1952  if (nGlobal_Tetr > 0) Conn_Tetr = Conn_Elem;
1953  break;
1954  case HEXAHEDRON:
1955  nGlobal_Hexa = nElem_Total;
1956  if (nGlobal_Hexa > 0) Conn_Hexa = Conn_Elem;
1957  break;
1958  case PRISM:
1959  nGlobal_Pris = nElem_Total;
1960  if (nGlobal_Pris > 0) Conn_Pris = Conn_Elem;
1961  break;
1962  case PYRAMID:
1963  nGlobal_Pyra = nElem_Total;
1964  if (nGlobal_Pyra > 0) Conn_Pyra = Conn_Elem;
1965  break;
1966  default:
1967  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
1968  break;
1969  }
1970  }
1971 
1972 }
1973 
1974 void COutput::MergeSurfaceConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) {
1975 
1976  unsigned short NODES_PER_ELEMENT;
1977 
1978  unsigned short iMarker;
1979  unsigned long iPoint, iNode, jNode;
1980  unsigned long iElem = 0;
1981  unsigned long nLocalElem = 0, nElem_Total = 0;
1982 
1983  int iProcessor;
1984  unsigned long jElem;
1985 
1986  unsigned long iVertex;
1987 
1988  int SendRecv, RecvFrom;
1989 
1990  unsigned long Buffer_Send_nElem[1], *Buffer_Recv_nElem = NULL;
1991  unsigned long nBuffer_Scalar = 0;
1992  unsigned long kNode = 0, kElem = 0;
1993  unsigned long MaxLocalElem = 0, iGlobal_Index, jPoint, kPoint;
1994 
1995  bool Wrt_Halo = config->GetWrt_Halo();
1996  bool *Write_Elem = NULL, notPeriodic, notHalo, addedPeriodic;
1997 
1998 
1999  int *Conn_Elem = NULL;
2000 
2001  /*--- Store the local number of this element type and the number of nodes
2002  per this element type. In serial, this will be the total number of this
2003  element type in the entire mesh. In parallel, it is the number on only
2004  the current partition. ---*/
2005 
2006  nLocalElem = 0;
2007 
2008  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
2009  if (config->GetMarker_All_Plotting(iMarker) == YES) {
2010  for (iElem = 0; iElem < geometry->GetnElem_Bound(iMarker); iElem++) {
2011  if (geometry->bound[iMarker][iElem]->GetVTK_Type() == Elem_Type) {
2012  nLocalElem++;
2013  }
2014  }
2015  }
2016  }
2017 
2018  switch (Elem_Type) {
2019  case LINE:
2020  NODES_PER_ELEMENT = N_POINTS_LINE;
2021  break;
2022  case TRIANGLE:
2023  NODES_PER_ELEMENT = N_POINTS_TRIANGLE;
2024  break;
2025  case QUADRILATERAL:
2026  NODES_PER_ELEMENT = N_POINTS_QUADRILATERAL;
2027  break;
2028  default:
2029  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
2030  NODES_PER_ELEMENT = 0;
2031  break;
2032  }
2033 
2034  /*--- Find the max number of this element type among all
2035  partitions and set up buffers. ---*/
2036 
2037  Buffer_Send_nElem[0] = nLocalElem;
2038  if (rank == MASTER_NODE) Buffer_Recv_nElem = new unsigned long[size];
2039 
2040 #ifdef HAVE_MPI
2041  SU2_MPI::Allreduce(&nLocalElem, &MaxLocalElem, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
2042  SU2_MPI::Gather(&Buffer_Send_nElem, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nElem, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
2043 #else
2044  MaxLocalElem = nLocalElem;
2045  Buffer_Recv_nElem[0] = Buffer_Send_nElem[0];
2046 #endif
2047 
2048  nBuffer_Scalar = MaxLocalElem*NODES_PER_ELEMENT;
2049 
2050  /*--- Send and Recv buffers ---*/
2051 
2052  unsigned long *Buffer_Send_Elem = new unsigned long[nBuffer_Scalar];
2053  unsigned long *Buffer_Recv_Elem = NULL;
2054 
2055  unsigned short *Buffer_Send_Halo = new unsigned short[MaxLocalElem];
2056  unsigned short *Buffer_Recv_Halo = NULL;
2057 
2058  /*--- Prepare the receive buffers on the master node only. ---*/
2059 
2060  if (rank == MASTER_NODE) {
2061  Buffer_Recv_Elem = new unsigned long[size*nBuffer_Scalar];
2062  Buffer_Recv_Halo = new unsigned short[size*MaxLocalElem];
2063  if (MaxLocalElem > 0) Conn_Elem = new int[size*MaxLocalElem*NODES_PER_ELEMENT];
2064  }
2065 
2066  /*--- Force the removal of all added periodic elements (use global index).
2067  First, we isolate and create a list of all added periodic points, excluding
2068  those that we part of the original domain (we want these to be in the
2069  output files). ---*/
2070 
2071  vector<unsigned long> Added_Periodic;
2072  Added_Periodic.clear();
2073  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
2074  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
2075  SendRecv = config->GetMarker_All_SendRecv(iMarker);
2076  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
2077  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
2078  if ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
2079  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 0) &&
2080  (SendRecv < 0)) {
2081  Added_Periodic.push_back(geometry->node[iPoint]->GetGlobalIndex());
2082  }
2083  }
2084  }
2085  }
2086 
2087  /*--- Now we communicate this information to all processors, so that they
2088  can force the removal of these particular nodes by flagging them as halo
2089  points. In general, this should be a small percentage of the total mesh,
2090  so the communication/storage costs here shouldn't be prohibitive. ---*/
2091 
2092  /*--- First communicate the number of points that each rank has found ---*/
2093  unsigned long nAddedPeriodic = 0, maxAddedPeriodic = 0;
2094  unsigned long Buffer_Send_nAddedPeriodic[1], *Buffer_Recv_nAddedPeriodic = NULL;
2095  Buffer_Recv_nAddedPeriodic = new unsigned long[size];
2096 
2097  nAddedPeriodic = Added_Periodic.size();
2098  Buffer_Send_nAddedPeriodic[0] = nAddedPeriodic;
2099 
2100 #ifdef HAVE_MPI
2101  SU2_MPI::Allreduce(&nAddedPeriodic, &maxAddedPeriodic, 1, MPI_UNSIGNED_LONG,
2103  SU2_MPI::Allgather(&Buffer_Send_nAddedPeriodic, 1, MPI_UNSIGNED_LONG,
2104  Buffer_Recv_nAddedPeriodic, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
2105 #else
2106  maxAddedPeriodic = nAddedPeriodic;
2107  Buffer_Recv_nAddedPeriodic[0] = Buffer_Send_nAddedPeriodic[0];
2108 #endif
2109 
2110  /*--- Communicate the global index values of all added periodic nodes. ---*/
2111  unsigned long *Buffer_Send_AddedPeriodic = new unsigned long[maxAddedPeriodic];
2112  unsigned long *Buffer_Recv_AddedPeriodic = new unsigned long[size*maxAddedPeriodic];
2113 
2114  for (iPoint = 0; iPoint < Added_Periodic.size(); iPoint++) {
2115  Buffer_Send_AddedPeriodic[iPoint] = Added_Periodic[iPoint];
2116  }
2117 
2118  /*--- Gather the element connectivity information. All processors will now
2119  have a copy of the global index values for all added periodic points. ---*/
2120 
2121 #ifdef HAVE_MPI
2122  SU2_MPI::Allgather(Buffer_Send_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
2123  Buffer_Recv_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
2124  MPI_COMM_WORLD);
2125 #else
2126  for (iPoint = 0; iPoint < maxAddedPeriodic; iPoint++) Buffer_Recv_AddedPeriodic[iPoint] = Buffer_Send_AddedPeriodic[iPoint];
2127 #endif
2128 
2129  /*--- Search all send/recv boundaries on this partition for halo cells. In
2130  particular, consider only the recv conditions (these are the true halo
2131  nodes). Check the ranks of the processors that are communicating and
2132  choose to keep only the halo cells from the higher rank processor. Here,
2133  we are also choosing to keep periodic nodes that were part of the original
2134  domain. We will check the communicated list of added periodic points. ---*/
2135 
2136  int *Local_Halo = new int[geometry->GetnPoint()];
2137  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
2138  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
2139 
2140  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
2141  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
2142  SendRecv = config->GetMarker_All_SendRecv(iMarker);
2143  RecvFrom = abs(SendRecv)-1;
2144 
2145  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
2146  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
2147  iGlobal_Index = geometry->node[iPoint]->GetGlobalIndex();
2148 
2149  /*--- We need to keep one copy of overlapping halo cells. ---*/
2150  notHalo = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() == 0) &&
2151  (SendRecv < 0) && (rank > RecvFrom));
2152 
2153  /*--- We want to keep the periodic nodes that were part of the original domain ---*/
2154  notPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
2155  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1) &&
2156  (SendRecv < 0));
2157 
2158  /*--- Lastly, check that this isn't an added periodic point that
2159  we will forcibly remove. Use the communicated list of these points. ---*/
2160  addedPeriodic = false; kPoint = 0;
2161  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2162  for (jPoint = 0; jPoint < Buffer_Recv_nAddedPeriodic[iProcessor]; jPoint++) {
2163  if (iGlobal_Index == Buffer_Recv_AddedPeriodic[kPoint+jPoint])
2164  addedPeriodic = true;
2165  }
2166  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
2167  kPoint = (iProcessor+1)*maxAddedPeriodic;
2168  }
2169 
2170  /*--- If we found either of these types of nodes, flag them to be kept. ---*/
2171  if ((notHalo || notPeriodic) && !addedPeriodic) {
2172  Local_Halo[iPoint] = false;
2173  }
2174  }
2175  }
2176  }
2177 
2178  /*--- Loop over all elements in this partition and load the
2179  elements of the current type into the buffer to be sent to
2180  the master node. ---*/
2181  jNode = 0; jElem = 0;
2182  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
2183  if (config->GetMarker_All_Plotting(iMarker) == YES)
2184  for (iElem = 0; iElem < geometry->GetnElem_Bound(iMarker); iElem++) {
2185 
2186  if (geometry->bound[iMarker][iElem]->GetVTK_Type() == Elem_Type) {
2187 
2188  /*--- Loop over all nodes in this element and load the
2189  connectivity into the send buffer. ---*/
2190 
2191  Buffer_Send_Halo[jElem] = false;
2192  for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) {
2193 
2194  /*--- Store the global index values directly. ---*/
2195 
2196  iPoint = geometry->bound[iMarker][iElem]->GetNode(iNode);
2197  Buffer_Send_Elem[jNode] = geometry->node[iPoint]->GetGlobalIndex();
2198 
2199  /*--- Check if this is a halo node. If so, flag this element
2200  as a halo cell. We will use this later to sort and remove
2201  any duplicates from the connectivity list. ---*/
2202 
2203  if (Local_Halo[iPoint])
2204  Buffer_Send_Halo[jElem] = true;
2205 
2206  /*--- Increment jNode as the counter. We need this because iElem
2207  may include other elements that we skip over during this loop. ---*/
2208 
2209  jNode++;
2210  }
2211  jElem++;
2212  }
2213  }
2214 
2215  /*--- Gather the element connectivity information. ---*/
2216 
2217 #ifdef HAVE_MPI
2218  SU2_MPI::Gather(Buffer_Send_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
2219  SU2_MPI::Gather(Buffer_Send_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, Buffer_Recv_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, MASTER_NODE, MPI_COMM_WORLD);
2220 #else
2221  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Elem[iPoint] = Buffer_Send_Elem[iPoint];
2222  for (iPoint = 0; iPoint < MaxLocalElem; iPoint++) Buffer_Recv_Halo[iPoint] = Buffer_Send_Halo[iPoint];
2223 #endif
2224 
2225  /*--- The master node unpacks and sorts the connectivity. ---*/
2226 
2227  if (rank == MASTER_NODE) {
2228 
2229  /*--- We need to remove any duplicate elements (halo cells) that
2230  exist on multiple partitions. Start by initializing all elements
2231  to the "write" state by using a boolean array. ---*/
2232 
2233  Write_Elem = new bool[size*MaxLocalElem];
2234  for (iElem = 0; iElem < size*MaxLocalElem; iElem++) {
2235  Write_Elem[iElem] = true;
2236  }
2237 
2238  /*--- Remove the rind layer from the solution only if requested ---*/
2239 
2240  if (!Wrt_Halo) {
2241 
2242  /*--- Loop for flagging duplicate elements so that they are not
2243  included in the final connectivity list. ---*/
2244 
2245  kElem = 0;
2246  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2247  for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) {
2248 
2249  /*--- Check if this element was marked as a halo. ---*/
2250  if (Buffer_Recv_Halo[kElem+iElem])
2251  Write_Elem[kElem+iElem] = false;
2252 
2253  }
2254  kElem = (iProcessor+1)*MaxLocalElem;
2255  }
2256  }
2257 
2258  /*--- Store the unique connectivity list for this element type. ---*/
2259 
2260  jNode = 0; kNode = 0; jElem = 0; nElem_Total = 0;
2261  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2262  for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) {
2263 
2264  /*--- Only write the elements that were flagged for it. ---*/
2265  if (Write_Elem[jElem+iElem]) {
2266 
2267  /*--- Increment total count for this element type ---*/
2268  nElem_Total++;
2269 
2270  /*--- Get global index, then loop over each variable and store.
2271  Note that we are adding one to the index value because CGNS/Tecplot
2272  use 1-based indexing.---*/
2273 
2274  for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) {
2275  Conn_Elem[kNode] = (int)Buffer_Recv_Elem[jNode+iElem*NODES_PER_ELEMENT+iNode] + 1;
2276  kNode++;
2277  }
2278  }
2279  }
2280  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
2281  jElem = (iProcessor+1)*MaxLocalElem;
2282  jNode = (iProcessor+1)*nBuffer_Scalar;
2283  }
2284  }
2285 
2286  /*--- Immediately release the temporary buffers. ---*/
2287  delete [] Buffer_Send_Elem;
2288  delete [] Buffer_Send_Halo;
2289  delete [] Buffer_Recv_nAddedPeriodic;
2290  delete [] Buffer_Send_AddedPeriodic;
2291  delete [] Buffer_Recv_AddedPeriodic;
2292  delete [] Local_Halo;
2293  if (rank == MASTER_NODE) {
2294  delete [] Buffer_Recv_nElem;
2295  delete [] Buffer_Recv_Elem;
2296  delete [] Buffer_Recv_Halo;
2297  delete [] Write_Elem;
2298  }
2299 
2300  /*--- Store the particular global element count in the class data,
2301  and set the class data pointer to the connectivity array. ---*/
2302 
2303  if (rank == MASTER_NODE) {
2304  switch (Elem_Type) {
2305  case LINE:
2306  nGlobal_Line = nElem_Total;
2307  if (nGlobal_Line > 0) Conn_Line = Conn_Elem;
2308  break;
2309  case TRIANGLE:
2310  nGlobal_BoundTria = nElem_Total;
2311  if (nGlobal_BoundTria > 0) Conn_BoundTria = Conn_Elem;
2312  break;
2313  case QUADRILATERAL:
2314  nGlobal_BoundQuad = nElem_Total;
2315  if (nGlobal_BoundQuad > 0) Conn_BoundQuad = Conn_Elem;
2316  break;
2317  default:
2318  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
2319  break;
2320  }
2321  }
2322 
2323 }
2324 
2325 void COutput::MergeSolution(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
2326 
2327  unsigned short Kind_Solver = config->GetKind_Solver();
2328  unsigned short iVar = 0, jVar = 0, FirstIndex = NONE, SecondIndex = NONE, ThirdIndex = NONE;
2329  unsigned short nVar_First = 0, nVar_Second = 0, nVar_Third = 0;
2330  unsigned short iVar_GridVel = 0, iVar_PressCp = 0, iVar_Lam = 0, iVar_MachMean = 0,
2331  iVar_ViscCoeffs = 0, iVar_HeatCoeffs = 0, iVar_Sens = 0, iVar_Extra = 0, iVar_Eddy = 0, iVar_Sharp = 0,
2332  iVar_FEA_Vel = 0, iVar_FEA_Accel = 0, iVar_FEA_Stress = 0, iVar_FEA_Stress_3D = 0,
2333  iVar_FEA_Extra = 0, iVar_SensDim = 0, iVar_Transp = 0;
2334  unsigned long iPoint = 0, jPoint = 0, iVertex = 0, iMarker = 0;
2335  su2double Gas_Constant, Mach2Vel, Mach_Motion, RefDensity, RefPressure = 0.0, factor = 0.0;
2336 
2337  su2double *Aux_Frict_x = NULL, *Aux_Frict_y = NULL, *Aux_Frict_z = NULL, *Aux_Heat = NULL, *Aux_yPlus = NULL, *Aux_Sens = NULL;
2338 
2339  unsigned short CurrentIndex;
2340  int *Local_Halo;
2341  unsigned long Buffer_Send_nPoint[1], *Buffer_Recv_nPoint = NULL;
2342  unsigned long nLocalPoint = 0, MaxLocalPoint = 0;
2343  unsigned long iGlobal_Index = 0, nBuffer_Scalar = 0;
2344  bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
2345 
2346  int iProcessor;
2347 
2348  bool grid_movement = (config->GetGrid_Movement());
2349  bool compressible = (config->GetKind_Regime() == COMPRESSIBLE);
2350  bool incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE);
2351  bool transition = (config->GetKind_Trans_Model() == LM);
2352  bool flow = (( config->GetKind_Solver() == EULER ) ||
2353  ( config->GetKind_Solver() == NAVIER_STOKES ) ||
2354  ( config->GetKind_Solver() == RANS ) ||
2355  ( config->GetKind_Solver() == FEM_EULER ) ||
2356  ( config->GetKind_Solver() == FEM_NAVIER_STOKES ) ||
2357  ( config->GetKind_Solver() == FEM_RANS ) ||
2358  ( config->GetKind_Solver() == FEM_LES ) ||
2359  ( config->GetKind_Solver() == ADJ_EULER ) ||
2360  ( config->GetKind_Solver() == ADJ_NAVIER_STOKES ) ||
2361  ( config->GetKind_Solver() == ADJ_RANS ) );
2362  bool fem = (config->GetKind_Solver() == FEM_ELASTICITY);
2363  bool transp = (config->GetnMarker_Transpiration() > 0);
2364 
2365  unsigned short iDim;
2366  unsigned short nDim = geometry->GetnDim();
2367  su2double RefArea = config->GetRefArea();
2368  su2double Gamma = config->GetGamma();
2369  su2double RefVel2, *Normal, Area;
2370 
2371  /*--- Set the non-dimensionalization ---*/
2372  if (flow) {
2373  if (grid_movement) {
2374  Gas_Constant = config->GetGas_ConstantND();
2375  Mach2Vel = sqrt(Gamma*Gas_Constant*config->GetTemperature_FreeStreamND());
2376  Mach_Motion = config->GetMach_Motion();
2377  RefVel2 = (Mach_Motion*Mach2Vel)*(Mach_Motion*Mach2Vel);
2378  }
2379  else {
2380  RefVel2 = 0.0;
2381  for (iDim = 0; iDim < nDim; iDim++)
2382  RefVel2 += solver[FLOW_SOL]->GetVelocity_Inf(iDim)*solver[FLOW_SOL]->GetVelocity_Inf(iDim);
2383  }
2384  RefDensity = solver[FLOW_SOL]->GetDensity_Inf();
2385  RefPressure = solver[FLOW_SOL]->GetPressure_Inf();
2386  factor = 1.0 / (0.5*RefDensity*RefArea*RefVel2);
2387  }
2388 
2389  /*--- Prepare send buffers for the conservative variables. Need to
2390  find the total number of conservative variables and also the
2391  index for their particular solution container. ---*/
2392 
2393  switch (Kind_Solver) {
2394  case EULER : case NAVIER_STOKES: FirstIndex = FLOW_SOL; if(config->GetWeakly_Coupled_Heat()) SecondIndex = HEAT_SOL; else SecondIndex = NONE; ThirdIndex = NONE; break;
2395  case RANS : FirstIndex = FLOW_SOL; SecondIndex = TURB_SOL; if (transition) ThirdIndex=TRANS_SOL; else ThirdIndex = NONE; if(config->GetWeakly_Coupled_Heat()) ThirdIndex = HEAT_SOL; else ThirdIndex = NONE; break;
2396  case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_LES: FirstIndex = FLOW_SOL; SecondIndex = NONE; ThirdIndex = NONE; break;
2397  case FEM_RANS : FirstIndex = FLOW_SOL; SecondIndex = TURB_SOL; break;
2398  case FEM_ELASTICITY: FirstIndex = FEA_SOL; SecondIndex = NONE; ThirdIndex = NONE; break;
2399  case ADJ_EULER : case ADJ_NAVIER_STOKES : FirstIndex = ADJFLOW_SOL; SecondIndex = NONE; ThirdIndex = NONE; break;
2400  case ADJ_RANS : FirstIndex = ADJFLOW_SOL; if (config->GetFrozen_Visc_Cont()) SecondIndex = NONE; else SecondIndex = ADJTURB_SOL; ThirdIndex = NONE; break;
2401  case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: FirstIndex = ADJFLOW_SOL; SecondIndex = NONE; ThirdIndex = NONE; break;
2402  case DISC_ADJ_RANS: FirstIndex = ADJFLOW_SOL; if (config->GetFrozen_Visc_Disc()) SecondIndex = NONE; else SecondIndex = ADJTURB_SOL; ThirdIndex = NONE; break;
2403  case DISC_ADJ_FEM: FirstIndex = ADJFEA_SOL; SecondIndex = NONE; ThirdIndex = NONE; break;
2404  default: SecondIndex = NONE; ThirdIndex = NONE; break;
2405  }
2406 
2407  nVar_First = solver[FirstIndex]->GetnVar();
2408  if (SecondIndex != NONE) nVar_Second = solver[SecondIndex]->GetnVar();
2409  if (ThirdIndex != NONE) nVar_Third = solver[ThirdIndex]->GetnVar();
2410  nVar_Consv = nVar_First + nVar_Second + nVar_Third;
2411  nVar_Total = nVar_Consv;
2412 
2413  if (!config->GetLow_MemoryOutput()) {
2414 
2415  /*--- Add the limiters ---*/
2416 
2417  if (config->GetWrt_Limiters()) nVar_Total += nVar_Consv;
2418 
2419  /*--- Add the residuals ---*/
2420 
2421  if (config->GetWrt_Residuals()) nVar_Total += nVar_Consv;
2422 
2423  /*--- Add the grid velocity to the restart file for the unsteady adjoint ---*/
2424 
2425  if (grid_movement && !fem) {
2426  iVar_GridVel = nVar_Total;
2427  if (geometry->GetnDim() == 2) nVar_Total += 2;
2428  else if (geometry->GetnDim() == 3) nVar_Total += 3;
2429  }
2430 
2431  /*--- Add Pressure, Temperature, Cp, Mach to the restart file ---*/
2432 
2433  if (Kind_Solver == EULER || Kind_Solver == NAVIER_STOKES || Kind_Solver == RANS ||
2434  Kind_Solver == FEM_EULER || Kind_Solver == FEM_NAVIER_STOKES || Kind_Solver == FEM_RANS ||
2435  Kind_Solver == FEM_LES) {
2436  iVar_PressCp = nVar_Total; nVar_Total += 3;
2437  iVar_MachMean = nVar_Total; nVar_Total += 1;
2438  }
2439 
2440  /*--- Add Laminar Viscosity, Skin Friction, Heat Flux, & yPlus to the restart file ---*/
2441 
2442  if (Kind_Solver == NAVIER_STOKES || Kind_Solver == RANS ||
2443  Kind_Solver == FEM_NAVIER_STOKES || Kind_Solver == FEM_RANS || Kind_Solver == FEM_LES) {
2444  iVar_Lam = nVar_Total;
2445  nVar_Total += 1;
2446  iVar_ViscCoeffs = nVar_Total;
2447  if (geometry->GetnDim() == 2) nVar_Total += 2;
2448  else if (geometry->GetnDim() == 3) nVar_Total += 3;
2449  iVar_HeatCoeffs = nVar_Total;
2450  nVar_Total += 2;
2451  }
2452 
2453  /*--- Add Eddy Viscosity to the restart file ---*/
2454 
2455  if (Kind_Solver == RANS || Kind_Solver == FEM_RANS || Kind_Solver == FEM_LES) {
2456  iVar_Eddy = nVar_Total; nVar_Total += 1;
2457  }
2458 
2459  /*--- Add Sharp edges to the restart file ---*/
2460 
2461  if (config->GetWrt_SharpEdges()) {
2462  if (((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) ||
2463  ((Kind_Solver == FEM_EULER) || (Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) {
2464  iVar_Sharp = nVar_Total; nVar_Total += 1;
2465  }
2466  }
2467 
2468 
2469  if (( Kind_Solver == ADJ_EULER ) ||
2470  ( Kind_Solver == ADJ_NAVIER_STOKES ) ||
2471  ( Kind_Solver == ADJ_RANS )) {
2472  iVar_Sens = nVar_Total; nVar_Total += 2;
2473  }
2474 
2475  if (Kind_Solver == FEM_ELASTICITY) {
2476  /*--- If the analysis is dynamic... ---*/
2477  if (config->GetDynamic_Analysis() == DYNAMIC) {
2478  /*--- Velocities ---*/
2479  iVar_FEA_Vel = nVar_Total;
2480  if (geometry->GetnDim() == 2) nVar_Total += 2;
2481  else if (geometry->GetnDim() == 3) nVar_Total += 3;
2482  /*--- Accelerations ---*/
2483  iVar_FEA_Accel = nVar_Total;
2484  if (geometry->GetnDim() == 2) nVar_Total += 2;
2485  else if (geometry->GetnDim() == 3) nVar_Total += 3;
2486  }
2487  iVar_FEA_Stress = nVar_Total; nVar_Total += 3;
2488  if (geometry->GetnDim() == 3) {iVar_FEA_Stress_3D = nVar_Total; nVar_Total += 3;}
2489  iVar_FEA_Extra = nVar_Total; nVar_Total += 1;
2490  }
2491 
2492  if ((Kind_Solver == DISC_ADJ_EULER) ||
2493  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
2494  (Kind_Solver == DISC_ADJ_RANS)) {
2495  iVar_Sens = nVar_Total; nVar_Total += 1;
2496  iVar_SensDim = nVar_Total; nVar_Total += nDim;
2497  }
2498 
2499  if (transp && ((Kind_Solver == DISC_ADJ_EULER) ||
2500  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
2501  (Kind_Solver == DISC_ADJ_RANS))) {
2502  iVar_Transp = nVar_Total;
2503  nVar_Total += 1;
2504  }
2505 
2506  if ((Kind_Solver == DISC_ADJ_FEM) && (config->GetFSI_Simulation())){
2507  iVar_FEA_Extra = nVar_Total; nVar_Total += 2;
2508  }
2509 
2510  if (config->GetExtraOutput()) {
2511  if (Kind_Solver == RANS) {
2512  iVar_Extra = nVar_Total; nVar_Extra = solver[TURB_SOL]->GetnOutputVariables(); nVar_Total += nVar_Extra;
2513  }
2514  }
2515 
2516  }
2517 
2518  Local_Halo = new int[geometry->GetnPoint()];
2519  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
2520  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
2521 
2522  /*--- Search all send/recv boundaries on this partition for any periodic
2523  nodes that were part of the original domain. We want to recover these
2524  for visualization purposes. ---*/
2525 
2526  if (Wrt_Halo) {
2527  nLocalPoint = geometry->GetnPoint();
2528  } else {
2529  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
2530  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
2531 
2532  /*--- Checking for less than or equal to the rank, because there may
2533  be some periodic halo nodes that send info to the same rank. ---*/
2534 
2535  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
2536  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
2537  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
2538  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
2539  if (isPeriodic) Local_Halo[iPoint] = false;
2540  }
2541  }
2542  }
2543 
2544  /*--- Sum total number of nodes that belong to the domain ---*/
2545 
2546  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
2547  if (Local_Halo[iPoint] == false)
2548  nLocalPoint++;
2549 
2550  }
2551  Buffer_Send_nPoint[0] = nLocalPoint;
2552 
2553  /*--- Each processor sends its local number of nodes to the master. ---*/
2554 
2555  if (rank == MASTER_NODE) Buffer_Recv_nPoint = new unsigned long[size];
2556 
2557 #ifdef HAVE_MPI
2558  SU2_MPI::Allreduce(&nLocalPoint, &MaxLocalPoint, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
2559  SU2_MPI::Gather(&Buffer_Send_nPoint, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nPoint, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
2560 #else
2561  MaxLocalPoint = nLocalPoint;
2562  Buffer_Recv_nPoint[0] = Buffer_Send_nPoint[0];
2563 #endif
2564 
2565  nBuffer_Scalar = MaxLocalPoint;
2566 
2567  /*--- Send and Recv buffers. ---*/
2568 
2569  su2double *Buffer_Send_Var = new su2double[MaxLocalPoint];
2570  su2double *Buffer_Recv_Var = NULL;
2571 
2572  su2double *Buffer_Send_Res = new su2double[MaxLocalPoint];
2573  su2double *Buffer_Recv_Res = NULL;
2574 
2575  su2double *Buffer_Send_Vol = new su2double[MaxLocalPoint];
2576  su2double *Buffer_Recv_Vol = NULL;
2577 
2578  unsigned long *Buffer_Send_GlobalIndex = new unsigned long[MaxLocalPoint];
2579  unsigned long *Buffer_Recv_GlobalIndex = NULL;
2580 
2581  /*--- Auxiliary vectors for surface coefficients ---*/
2582 
2583  if (((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) ||
2584  ((Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) {
2585  Aux_Frict_x = new su2double[geometry->GetnPoint()];
2586  Aux_Frict_y = new su2double[geometry->GetnPoint()];
2587  Aux_Frict_z = new su2double[geometry->GetnPoint()];
2588  Aux_Heat = new su2double[geometry->GetnPoint()];
2589  Aux_yPlus = new su2double[geometry->GetnPoint()];
2590  }
2591 
2592  if ((Kind_Solver == ADJ_EULER) ||
2593  (Kind_Solver == ADJ_NAVIER_STOKES) ||
2594  (Kind_Solver == ADJ_RANS) ||
2595  (Kind_Solver == DISC_ADJ_EULER) ||
2596  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
2597  (Kind_Solver == DISC_ADJ_RANS)) {
2598  Aux_Sens = new su2double[geometry->GetnPoint()];
2599  }
2600 
2601  /*--- Prepare the receive buffers in the master node only. ---*/
2602 
2603  if (rank == MASTER_NODE) {
2604 
2605  Buffer_Recv_Var = new su2double[size*MaxLocalPoint];
2606  Buffer_Recv_Res = new su2double[size*MaxLocalPoint];
2607  Buffer_Recv_Vol = new su2double[size*MaxLocalPoint];
2608  Buffer_Recv_GlobalIndex = new unsigned long[size*MaxLocalPoint];
2609 
2610  /*--- Sum total number of nodes to be written and allocate arrays ---*/
2611  nGlobal_Poin = 0;
2612  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2613  nGlobal_Poin += Buffer_Recv_nPoint[iProcessor];
2614  }
2615  Data = new su2double*[nVar_Total];
2616  for (iVar = 0; iVar < nVar_Total; iVar++) {
2617  Data[iVar] = new su2double[nGlobal_Poin];
2618  }
2619  }
2620 
2621  /*--- Main communication routine. Loop over each variable that has
2622  been requested by the user and perform the MPI comm. Temporary
2623  1-D buffers are used to send the solution for each variable at all
2624  nodes on each partition to the master node. These are then unpacked
2625  by the master and sorted by global index in one large n-dim. array. ---*/
2626 
2627  for (iVar = 0; iVar < nVar_Consv; iVar++) {
2628 
2629  /*--- Logic for which solution class to draw from. ---*/
2630 
2631  jVar = iVar;
2632  CurrentIndex = FirstIndex;
2633  if ((SecondIndex != NONE) && (iVar > nVar_First-1)) {
2634  jVar = iVar - nVar_First;
2635  CurrentIndex = SecondIndex;
2636  }
2637  if ((SecondIndex != NONE) && (ThirdIndex != NONE) && (iVar > (nVar_First + nVar_Second-1))) {
2638  jVar = iVar - nVar_First - nVar_Second;
2639  CurrentIndex = ThirdIndex;
2640  }
2641 
2642  /*--- Loop over this partition to collect the current variable ---*/
2643 
2644  jPoint = 0;
2645  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
2646 
2647  /*--- Check for halos & write only if requested ---*/
2648 
2649  if (!Local_Halo[iPoint] || Wrt_Halo) {
2650 
2651  /*--- Get this variable into the temporary send buffer. ---*/
2652 
2653  Buffer_Send_Var[jPoint] = solver[CurrentIndex]->node[iPoint]->GetSolution(jVar);
2654 
2655  if (!config->GetLow_MemoryOutput()) {
2656 
2657  if (config->GetWrt_Limiters()) {
2658  Buffer_Send_Vol[jPoint] = solver[CurrentIndex]->node[iPoint]->GetLimiter_Primitive(jVar);
2659  }
2660 
2661  if (config->GetWrt_Residuals()) {
2662  if (!config->GetDiscrete_Adjoint()) {
2663  Buffer_Send_Res[jPoint] = solver[CurrentIndex]->LinSysRes.GetBlock(iPoint, jVar);
2664  } else {
2665  Buffer_Send_Res[jPoint] = solver[CurrentIndex]->node[iPoint]->GetSolution(jVar) -
2666  solver[CurrentIndex]->node[iPoint]->GetSolution_Old(jVar);
2667  }
2668  }
2669 
2670  }
2671 
2672  /*--- Only send/recv the volumes & global indices during the first loop ---*/
2673 
2674  if (iVar == 0) {
2675  Buffer_Send_GlobalIndex[jPoint] = geometry->node[iPoint]->GetGlobalIndex();
2676  }
2677 
2678  jPoint++;
2679 
2680  }
2681  }
2682 
2683  /*--- Gather the data on the master node. ---*/
2684 
2685 #ifdef HAVE_MPI
2686  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2687 #else
2688  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
2689 #endif
2690  if (!config->GetLow_MemoryOutput()) {
2691 
2692  if (config->GetWrt_Limiters()) {
2693 #ifdef HAVE_MPI
2694  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2695 #else
2696  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
2697 #endif
2698  }
2699 
2700  if (config->GetWrt_Residuals()) {
2701 #ifdef HAVE_MPI
2702  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2703 #else
2704  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
2705 #endif
2706  }
2707 
2708  }
2709 
2710  if (iVar == 0) {
2711 #ifdef HAVE_MPI
2712  SU2_MPI::Gather(Buffer_Send_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
2713 #else
2714  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_GlobalIndex[iPoint] = Buffer_Send_GlobalIndex[iPoint];
2715 #endif
2716  }
2717 
2718  /*--- The master node unpacks and sorts this variable by global index ---*/
2719 
2720  if (rank == MASTER_NODE) {
2721  jPoint = 0;
2722  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2723  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
2724 
2725  /*--- Get global index, then loop over each variable and store ---*/
2726 
2727  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
2728 
2729  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
2730 
2731  if (!config->GetLow_MemoryOutput()) {
2732 
2733  if (config->GetWrt_Limiters()) {
2734  Data[iVar+nVar_Consv][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
2735  }
2736 
2737  if (config->GetWrt_Residuals()) {
2738  unsigned short ExtraIndex;
2739  ExtraIndex = nVar_Consv;
2740  if (config->GetWrt_Limiters()) ExtraIndex = 2*nVar_Consv;
2741  Data[iVar+ExtraIndex][iGlobal_Index] = Buffer_Recv_Res[jPoint];
2742  }
2743 
2744  }
2745 
2746  jPoint++;
2747  }
2748  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
2749  jPoint = (iProcessor+1)*nBuffer_Scalar;
2750  }
2751  }
2752 
2753  }
2754 
2755  if (!config->GetLow_MemoryOutput()) {
2756 
2757  /*--- Additional communication routine for the grid velocity. Note that
2758  we are reusing the same temporary buffers from above for efficiency.
2759  Also, in the future more routines like this could be used to write
2760  an arbitrary number of additional variables to the file. ---*/
2761 
2762  if (grid_movement && !fem) {
2763 
2764  /*--- Loop over this partition to collect the current variable ---*/
2765 
2766  jPoint = 0; su2double *Grid_Vel;
2767  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
2768 
2769  /*--- Check for halos & write only if requested ---*/
2770 
2771  if (!Local_Halo[iPoint] || Wrt_Halo) {
2772 
2773  /*--- Load buffers with the three grid velocity components. ---*/
2774 
2775  Grid_Vel = geometry->node[iPoint]->GetGridVel();
2776  Buffer_Send_Var[jPoint] = Grid_Vel[0];
2777  Buffer_Send_Res[jPoint] = Grid_Vel[1];
2778  if (geometry->GetnDim() == 3) Buffer_Send_Vol[jPoint] = Grid_Vel[2];
2779  jPoint++;
2780  }
2781  }
2782 
2783  /*--- Gather the data on the master node. ---*/
2784 
2785 #ifdef HAVE_MPI
2786  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2787  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2788  if (geometry->GetnDim() == 3) {
2789  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2790  }
2791 #else
2792  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
2793  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
2794  if (geometry->GetnDim() == 3) {
2795  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
2796  }
2797 #endif
2798 
2799  /*--- The master node unpacks and sorts this variable by global index ---*/
2800 
2801  if (rank == MASTER_NODE) {
2802  jPoint = 0; iVar = iVar_GridVel;
2803  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2804  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
2805 
2806  /*--- Get global index, then loop over each variable and store ---*/
2807 
2808  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
2809  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
2810  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
2811  if (geometry->GetnDim() == 3)
2812  Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
2813  jPoint++;
2814  }
2815 
2816  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
2817 
2818  jPoint = (iProcessor+1)*nBuffer_Scalar;
2819  }
2820  }
2821  }
2822 
2823  /*--- Communicate Pressure, Cp, and Mach ---*/
2824 
2825  if (((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) ||
2826  ((Kind_Solver == FEM_EULER) || (Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) {
2827 
2828  /*--- First, loop through the mesh in order to find and store the
2829  value of the coefficient of pressure at any surface nodes. They
2830  will be placed in an auxiliary vector and then communicated like
2831  all other volumetric variables. ---*/
2832 
2833  /*--- Loop over this partition to collect the current variable ---*/
2834 
2835  jPoint = 0;
2836  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
2837 
2838  /*--- Check for halos & write only if requested ---*/
2839 
2840  if (!Local_Halo[iPoint] || Wrt_Halo) {
2841 
2842  /*--- Load buffers with the pressure, Cp, and mach variables. ---*/
2843 
2844  Buffer_Send_Var[jPoint] = solver[FLOW_SOL]->node[iPoint]->GetPressure();
2845  if (compressible){
2846  Buffer_Send_Res[jPoint] = solver[FLOW_SOL]->node[iPoint]->GetTemperature();
2847  } else{
2848  Buffer_Send_Res[jPoint] = 0.0;
2849  }
2850  Buffer_Send_Vol[jPoint] = (solver[FLOW_SOL]->node[iPoint]->GetPressure() - RefPressure)*factor*RefArea;
2851 
2852  jPoint++;
2853  }
2854  }
2855 
2856  /*--- Gather the data on the master node. ---*/
2857 
2858 #ifdef HAVE_MPI
2859  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2860  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2861  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2862 #else
2863  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
2864  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
2865  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
2866 #endif
2867 
2868  /*--- The master node unpacks and sorts this variable by global index ---*/
2869 
2870  if (rank == MASTER_NODE) {
2871  jPoint = 0; iVar = iVar_PressCp;
2872  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2873  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
2874 
2875  /*--- Get global index, then loop over each variable and store ---*/
2876 
2877  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
2878  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
2879  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
2880  Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
2881  jPoint++;
2882  }
2883 
2884  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
2885 
2886  jPoint = (iProcessor+1)*nBuffer_Scalar;
2887  }
2888  }
2889  }
2890 
2891  /*--- Communicate Mach---*/
2892 
2893  if (((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) ||
2894  ((Kind_Solver == FEM_EULER) || (Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) {
2895 
2896  /*--- Loop over this partition to collect the current variable ---*/
2897 
2898  jPoint = 0;
2899  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
2900 
2901  /*--- Check for halos & write only if requested ---*/
2902 
2903  if (!Local_Halo[iPoint] || Wrt_Halo) {
2904 
2905  /*--- Load buffers with the temperature and laminar viscosity variables. ---*/
2906 
2907  if (compressible) {
2908  Buffer_Send_Var[jPoint] = sqrt(solver[FLOW_SOL]->node[iPoint]->GetVelocity2())/
2909  solver[FLOW_SOL]->node[iPoint]->GetSoundSpeed();
2910  }
2911  if (incompressible) {
2912  Buffer_Send_Var[jPoint] = sqrt(solver[FLOW_SOL]->node[iPoint]->GetVelocity2())*config->GetVelocity_Ref()/
2913  sqrt(config->GetBulk_Modulus()/(solver[FLOW_SOL]->node[iPoint]->GetDensity()*config->GetDensity_Ref()));
2914  }
2915  jPoint++;
2916  }
2917  }
2918 
2919  /*--- Gather the data on the master node. ---*/
2920 
2921 #ifdef HAVE_MPI
2922  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2923 #else
2924  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
2925 #endif
2926 
2927  /*--- The master node unpacks and sorts this variable by global index ---*/
2928 
2929  if (rank == MASTER_NODE) {
2930  jPoint = 0; iVar = iVar_MachMean;
2931  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2932  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
2933 
2934  /*--- Get global index, then loop over each variable and store ---*/
2935 
2936  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
2937  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
2938  jPoint++;
2939  }
2940 
2941  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
2942 
2943  jPoint = (iProcessor+1)*nBuffer_Scalar;
2944  }
2945  }
2946  }
2947 
2948  /*--- Laminar Viscosity ---*/
2949 
2950  if (((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) ||
2951  ((Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) {
2952 
2953  /*--- Loop over this partition to collect the current variable ---*/
2954 
2955  jPoint = 0;
2956  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
2957 
2958  /*--- Check for halos & write only if requested ---*/
2959 
2960  if (!Local_Halo[iPoint] || Wrt_Halo) {
2961 
2962  /*--- Load buffers with the temperature and laminar viscosity variables. ---*/
2963 
2964  Buffer_Send_Res[jPoint] = solver[FLOW_SOL]->node[iPoint]->GetLaminarViscosity();
2965 
2966  jPoint++;
2967  }
2968  }
2969 
2970  /*--- Gather the data on the master node. ---*/
2971 
2972 #ifdef HAVE_MPI
2973  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
2974 #else
2975  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
2976 #endif
2977 
2978  /*--- The master node unpacks and sorts this variable by global index ---*/
2979 
2980  if (rank == MASTER_NODE) {
2981  jPoint = 0; iVar = iVar_Lam;
2982  for (iProcessor = 0; iProcessor < size; iProcessor++) {
2983  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
2984 
2985  /*--- Get global index, then loop over each variable and store ---*/
2986 
2987  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
2988  Data[iVar][iGlobal_Index] = Buffer_Recv_Res[jPoint];
2989  jPoint++;
2990  }
2991 
2992  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
2993 
2994  jPoint = (iProcessor+1)*nBuffer_Scalar;
2995  }
2996  }
2997 
2998  /*--- Communicate skin friction ---*/
2999 
3000  /*--- First, loop through the mesh in order to find and store the
3001  value of the viscous coefficients at any surface nodes. They
3002  will be placed in an auxiliary vector and then communicated like
3003  all other volumetric variables. ---*/
3004 
3005  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3006  Aux_Frict_x[iPoint] = 0.0;
3007  Aux_Frict_y[iPoint] = 0.0;
3008  Aux_Frict_z[iPoint] = 0.0;
3009  }
3010  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
3011  if (config->GetMarker_All_Plotting(iMarker) == YES) {
3012  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
3013  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
3014  Aux_Frict_x[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 0);
3015  Aux_Frict_y[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 1);
3016  if (geometry->GetnDim() == 3) Aux_Frict_z[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 2);
3017  }
3018  }
3019 
3020  /*--- Loop over this partition to collect the current variable ---*/
3021 
3022  jPoint = 0;
3023  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3024 
3025  /*--- Check for halos & write only if requested ---*/
3026 
3027  if (!Local_Halo[iPoint] || Wrt_Halo) {
3028 
3029  /*--- Load buffers with the three grid velocity components. ---*/
3030 
3031  Buffer_Send_Var[jPoint] = Aux_Frict_x[iPoint];
3032  Buffer_Send_Res[jPoint] = Aux_Frict_y[iPoint];
3033  if (geometry->GetnDim() == 3)
3034  Buffer_Send_Vol[jPoint] = Aux_Frict_z[iPoint];
3035  jPoint++;
3036  }
3037  }
3038 
3039  /*--- Gather the data on the master node. ---*/
3040 
3041 #ifdef HAVE_MPI
3042  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3043  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3044  if (geometry->GetnDim() == 3) {
3045  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3046  }
3047 #else
3048  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++)
3049  Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3050  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++)
3051  Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3052  if (geometry->GetnDim() == 3) {
3053  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++)
3054  Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
3055  }
3056 #endif
3057 
3058  /*--- The master node unpacks and sorts this variable by global index ---*/
3059 
3060  if (rank == MASTER_NODE) {
3061  jPoint = 0;
3062  iVar = iVar_ViscCoeffs;
3063  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3064  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3065 
3066  /*--- Get global index, then loop over each variable and store ---*/
3067 
3068  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3069  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3070  Data[iVar + 1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3071  if (geometry->GetnDim() == 3)
3072  Data[iVar + 2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
3073  jPoint++;
3074  }
3075 
3076  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3077 
3078  jPoint = (iProcessor + 1) * nBuffer_Scalar;
3079  }
3080  }
3081 
3082  /*--- Communicate heat transfer, y+ ---*/
3083 
3084  /*--- First, loop through the mesh in order to find and store the
3085  value of the viscous coefficients at any surface nodes. They
3086  will be placed in an auxiliary vector and then communicated like
3087  all other volumetric variables. ---*/
3088 
3089  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3090  Aux_Heat[iPoint] = 0.0;
3091  Aux_yPlus[iPoint] = 0.0;
3092  }
3093  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
3094  if (config->GetMarker_All_Plotting(iMarker) == YES) {
3095  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
3096  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
3097  Aux_Heat[iPoint] = solver[FLOW_SOL]->GetHeatFlux(iMarker, iVertex);
3098  Aux_yPlus[iPoint] = solver[FLOW_SOL]->GetYPlus(iMarker, iVertex);
3099  }
3100  }
3101 
3102  /*--- Loop over this partition to collect the current variable ---*/
3103 
3104  jPoint = 0;
3105  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3106 
3107  /*--- Check for halos & write only if requested ---*/
3108 
3109  if (!Local_Halo[iPoint] || Wrt_Halo) {
3110 
3111  /*--- Load buffers with the skin friction, heat transfer, y+ variables. ---*/
3112 
3113  if (compressible) {
3114  Buffer_Send_Res[jPoint] = Aux_Heat[iPoint];
3115  Buffer_Send_Vol[jPoint] = Aux_yPlus[iPoint];
3116  }
3117  if (incompressible) {
3118  Buffer_Send_Res[jPoint] = Aux_Heat[iPoint];
3119  Buffer_Send_Vol[jPoint] = Aux_yPlus[iPoint];
3120  }
3121  jPoint++;
3122  }
3123  }
3124 
3125  /*--- Gather the data on the master node. ---*/
3126 
3127 #ifdef HAVE_MPI
3128  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3129  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3130 #else
3131  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++)
3132  Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3133  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++)
3134  Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
3135 #endif
3136 
3137  /*--- The master node unpacks and sorts this variable by global index ---*/
3138 
3139  if (rank == MASTER_NODE) {
3140  jPoint = 0;
3141  iVar = iVar_HeatCoeffs;
3142 
3143  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3144  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3145 
3146  /*--- Get global index, then loop over each variable and store ---*/
3147 
3148  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3149  Data[iVar + 0][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3150  Data[iVar + 1][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
3151  jPoint++;
3152  }
3153 
3154  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3155 
3156  jPoint = (iProcessor + 1) * nBuffer_Scalar;
3157  }
3158  }
3159  }
3160 
3161 
3162  /*--- Communicate the Eddy Viscosity ---*/
3163 
3164  if (Kind_Solver == RANS || Kind_Solver == FEM_RANS || Kind_Solver == FEM_LES) {
3165 
3166  /*--- Loop over this partition to collect the current variable ---*/
3167 
3168  jPoint = 0;
3169  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3170 
3171  /*--- Check for halos & write only if requested ---*/
3172 
3173  if (!Local_Halo[iPoint] || Wrt_Halo) {
3174 
3175  /*--- Load buffers with the pressure and mach variables. ---*/
3176 
3177  Buffer_Send_Var[jPoint] = solver[FLOW_SOL]->node[iPoint]->GetEddyViscosity();
3178 
3179  jPoint++;
3180  }
3181  }
3182 
3183  /*--- Gather the data on the master node. ---*/
3184 
3185 #ifdef HAVE_MPI
3186  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3187 #else
3188  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3189 #endif
3190 
3191  /*--- The master node unpacks and sorts this variable by global index ---*/
3192 
3193  if (rank == MASTER_NODE) {
3194  jPoint = 0; iVar = iVar_Eddy;
3195  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3196  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3197 
3198  /*--- Get global index, then loop over each variable and store ---*/
3199 
3200  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3201  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3202  jPoint++;
3203  }
3204 
3205  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3206 
3207  jPoint = (iProcessor+1)*nBuffer_Scalar;
3208  }
3209  }
3210 
3211  }
3212 
3213  /*--- Communicate the Sharp Edges ---*/
3214 
3215  if (config->GetWrt_SharpEdges()) {
3216 
3217  if (((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) ||
3218  ((Kind_Solver == FEM_EULER) || (Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) {
3219 
3220  /*--- Loop over this partition to collect the current variable ---*/
3221  jPoint = 0;
3222  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3223 
3224  /*--- Check for halos & write only if requested ---*/
3225 
3226  if (!Local_Halo[iPoint] || Wrt_Halo) {
3227 
3228  /*--- Load buffers with the pressure and mach variables. ---*/
3229 
3230  Buffer_Send_Var[jPoint] = geometry->node[iPoint]->GetSharpEdge_Distance();
3231  jPoint++;
3232  }
3233  }
3234 
3235  /*--- Gather the data on the master node. ---*/
3236 
3237 #ifdef HAVE_MPI
3238  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3239 #else
3240  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3241 #endif
3242 
3243  /*--- The master node unpacks and sorts this variable by global index ---*/
3244 
3245  if (rank == MASTER_NODE) {
3246  jPoint = 0; iVar = iVar_Sharp;
3247  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3248  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3249 
3250  /*--- Get global index, then loop over each variable and store ---*/
3251 
3252  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3253  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3254  jPoint++;
3255  }
3256 
3257  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3258 
3259  jPoint = (iProcessor+1)*nBuffer_Scalar;
3260  }
3261  }
3262  }
3263  }
3264 
3265  /*--- Communicate the surface sensitivity ---*/
3266 
3267  if ((Kind_Solver == ADJ_EULER) ||
3268  (Kind_Solver == ADJ_NAVIER_STOKES) ||
3269  (Kind_Solver == ADJ_RANS) ||
3270  (Kind_Solver == DISC_ADJ_EULER) ||
3271  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
3272  (Kind_Solver == DISC_ADJ_RANS)) {
3273 
3274  /*--- First, loop through the mesh in order to find and store the
3275  value of the surface sensitivity at any surface nodes. They
3276  will be placed in an auxiliary vector and then communicated like
3277  all other volumetric variables. ---*/
3278 
3279  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Aux_Sens[iPoint] = 0.0;
3280  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
3281  if (config->GetMarker_All_Plotting(iMarker) == YES) {
3282  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
3283  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
3284  Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
3285  Area = 0.0;
3286  for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim];
3287  Area = sqrt (Area);
3288  Aux_Sens[iPoint] = solver[ADJFLOW_SOL]->GetCSensitivity(iMarker, iVertex)/Area;
3289  }
3290  }
3291 
3292  /*--- Loop over this partition to collect the current variable ---*/
3293 
3294  jPoint = 0;
3295  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3296 
3297  /*--- Check for halos & write only if requested ---*/
3298 
3299  if (!Local_Halo[iPoint] || Wrt_Halo) {
3300 
3301  /*--- Load buffers with the skin friction, heat transfer, y+ variables. ---*/
3302 
3303  Buffer_Send_Var[jPoint] = Aux_Sens[iPoint];
3304  if ((config->GetKind_ConvNumScheme() == SPACE_CENTERED) && (!config->GetDiscrete_Adjoint()))
3305  Buffer_Send_Res[jPoint] = solver[ADJFLOW_SOL]->node[iPoint]->GetSensor(iPoint);
3306  if ((config->GetKind_ConvNumScheme() == SPACE_UPWIND) && (!config->GetDiscrete_Adjoint()))
3307  Buffer_Send_Res[jPoint] = solver[ADJFLOW_SOL]->node[iPoint]->GetLimiter(0);
3308 
3309  jPoint++;
3310  }
3311  }
3312 
3313  /*--- Gather the data on the master node. ---*/
3314 
3315 #ifdef HAVE_MPI
3316  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3317  if (!config->GetDiscrete_Adjoint())
3318  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3319 #else
3320  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3321  if (!config->GetDiscrete_Adjoint())
3322  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3323 #endif
3324 
3325  /*--- The master node unpacks and sorts this variable by global index ---*/
3326 
3327  if (rank == MASTER_NODE) {
3328  jPoint = 0; iVar = iVar_Sens;
3329  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3330  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3331 
3332  /*--- Get global index, then loop over each variable and store ---*/
3333 
3334  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3335  Data[iVar+0][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3336  if (!config->GetDiscrete_Adjoint())
3337  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3338  jPoint++;
3339  }
3340 
3341  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3342 
3343  jPoint = (iProcessor+1)*nBuffer_Scalar;
3344  }
3345  }
3346  }
3347 
3348  if ((Kind_Solver == DISC_ADJ_EULER) ||
3349  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
3350  (Kind_Solver == DISC_ADJ_RANS)) {
3351  /*--- Loop over this partition to collect the current variable ---*/
3352 
3353  jPoint = 0;
3354  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3355 
3356  /*--- Check for halos & write only if requested ---*/
3357 
3358  if (!Local_Halo[iPoint] || Wrt_Halo) {
3359 
3360  /*--- Load buffers with the skin friction, heat transfer, y+ variables. ---*/
3361 
3362  Buffer_Send_Var[jPoint] = solver[ADJFLOW_SOL]->node[iPoint]->GetSensitivity(0);
3363  Buffer_Send_Res[jPoint] = solver[ADJFLOW_SOL]->node[iPoint]->GetSensitivity(1);
3364  if (nDim == 3)
3365  Buffer_Send_Vol[jPoint] = solver[ADJFLOW_SOL]->node[iPoint]->GetSensitivity(2);
3366  jPoint++;
3367  }
3368  }
3369 
3370  /*--- Gather the data on the master node. ---*/
3371 
3372 #ifdef HAVE_MPI
3373  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3374  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3375  if (nDim == 3)
3376  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3377 #else
3378  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3379  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3380  if (nDim == 3)
3381  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
3382 #endif
3383 
3384  /*--- The master node unpacks and sorts this variable by global index ---*/
3385 
3386  if (rank == MASTER_NODE) {
3387  jPoint = 0; iVar = iVar_SensDim;
3388  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3389  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3390 
3391  /*--- Get global index, then loop over each variable and store ---*/
3392 
3393  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3394  Data[iVar+0][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3395  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3396  if (nDim == 3)
3397  Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
3398  jPoint++;
3399  }
3400 
3401  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3402 
3403  jPoint = (iProcessor+1)*nBuffer_Scalar;
3404  }
3405  }
3406  }
3407 
3408  if (transp && ((Kind_Solver == DISC_ADJ_EULER) ||
3409  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
3410  (Kind_Solver == DISC_ADJ_RANS))) {
3411  /*--- Loop over this partition to collect the current variable ---*/
3412 
3413  jPoint = 0;
3414  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3415 
3416  /*--- Check for halos & write only if requested ---*/
3417 
3418  if (!Local_Halo[iPoint] || Wrt_Halo) {
3419 
3420  /*--- Load buffers with the skin friction, heat transfer, y+ variables. ---*/
3421 
3422  Buffer_Send_Var[jPoint] = solver[ADJFLOW_SOL]->node[iPoint]->GetSensitivityTranspiration();
3423  }
3424  }
3425 
3426  /*--- Gather the data on the master node. ---*/
3427 
3428 #ifdef HAVE_MPI
3429  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3430 #else
3431  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3432 #endif
3433 
3434  /*--- The master node unpacks and sorts this variable by global index ---*/
3435 
3436  if (rank == MASTER_NODE) {
3437  jPoint = 0; iVar = iVar_Transp;
3438  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3439  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3440 
3441  /*--- Get global index, then loop over each variable and store ---*/
3442 
3443  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3444  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3445 
3446  jPoint++;
3447  }
3448 
3449  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3450 
3451  jPoint = (iProcessor+1)*nBuffer_Scalar;
3452  }
3453  }
3454  }
3455 
3456  /*--- Communicate the Velocities for dynamic FEM problem ---*/
3457 
3458  if ((Kind_Solver == FEM_ELASTICITY) && (config->GetDynamic_Analysis() == DYNAMIC)) {
3459 
3460  /*--- Loop over this partition to collect the current variable ---*/
3461 
3462  jPoint = 0; su2double *Node_Vel;
3463  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3464 
3465  /*--- Check for halos & write only if requested ---*/
3466 
3467  if (!Local_Halo[iPoint] || Wrt_Halo) {
3468 
3469  /*--- Load buffers with the three grid velocity components. ---*/
3470 
3471  Node_Vel = solver[FEA_SOL]->node[iPoint]->GetSolution_Vel();
3472  Buffer_Send_Var[jPoint] = Node_Vel[0];
3473  Buffer_Send_Res[jPoint] = Node_Vel[1];
3474  if (geometry->GetnDim() == 3) Buffer_Send_Vol[jPoint] = Node_Vel[2];
3475  jPoint++;
3476  }
3477  }
3478 
3479  /*--- Gather the data on the master node. ---*/
3480 
3481 #ifdef HAVE_MPI
3482  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3483  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3484  if (geometry->GetnDim() == 3) {
3485  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3486  }
3487 #else
3488  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3489  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3490  if (geometry->GetnDim() == 3) {
3491  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
3492  }
3493 #endif
3494 
3495  /*--- The master node unpacks and sorts this variable by global index ---*/
3496 
3497  if (rank == MASTER_NODE) {
3498  jPoint = 0; iVar = iVar_FEA_Vel;
3499  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3500  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3501 
3502  /*--- Get global index, then loop over each variable and store ---*/
3503 
3504  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3505  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3506  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3507  if (geometry->GetnDim() == 3)
3508  Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
3509  jPoint++;
3510  }
3511 
3512  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3513 
3514  jPoint = (iProcessor+1)*nBuffer_Scalar;
3515  }
3516  }
3517  }
3518 
3519  /*--- Communicate the Accelerations for dynamic FEM problem ---*/
3520 
3521  if ((Kind_Solver == FEM_ELASTICITY) && (config->GetDynamic_Analysis() == DYNAMIC)) {
3522 
3523  /*--- Loop over this partition to collect the current variable ---*/
3524 
3525  jPoint = 0; su2double *Node_Accel;
3526  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3527 
3528  /*--- Check for halos & write only if requested ---*/
3529 
3530  if (!Local_Halo[iPoint] || Wrt_Halo) {
3531 
3532  /*--- Load buffers with the three grid velocity components. ---*/
3533 
3534  Node_Accel = solver[FEA_SOL]->node[iPoint]->GetSolution_Accel();
3535  Buffer_Send_Var[jPoint] = Node_Accel[0];
3536  Buffer_Send_Res[jPoint] = Node_Accel[1];
3537  if (geometry->GetnDim() == 3) Buffer_Send_Vol[jPoint] = Node_Accel[2];
3538  jPoint++;
3539  }
3540  }
3541 
3542  /*--- Gather the data on the master node. ---*/
3543 
3544 #ifdef HAVE_MPI
3545  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3546  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3547  if (geometry->GetnDim() == 3) {
3548  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3549  }
3550 #else
3551  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3552  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3553  if (geometry->GetnDim() == 3) {
3554  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
3555  }
3556 #endif
3557 
3558  /*--- The master node unpacks and sorts this variable by global index ---*/
3559 
3560  if (rank == MASTER_NODE) {
3561  jPoint = 0; iVar = iVar_FEA_Accel;
3562  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3563  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3564 
3565  /*--- Get global index, then loop over each variable and store ---*/
3566 
3567  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3568  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3569  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3570  if (geometry->GetnDim() == 3)
3571  Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
3572  jPoint++;
3573  }
3574 
3575  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3576 
3577  jPoint = (iProcessor+1)*nBuffer_Scalar;
3578  }
3579  }
3580  }
3581 
3582  /*--- Communicate the FEM elasticity stresses (2D) - New elasticity solver---*/
3583 
3584  if (Kind_Solver == FEM_ELASTICITY) {
3585 
3586  /*--- Loop over this partition to collect the current variable ---*/
3587 
3588  jPoint = 0; su2double *Stress;
3589  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3590 
3591  /*--- Check for halos & write only if requested ---*/
3592 
3593  if (!Local_Halo[iPoint] || Wrt_Halo) {
3594 
3595  /*--- Load buffers with the three grid velocity components. ---*/
3596 
3597  Stress = solver[FEA_SOL]->node[iPoint]->GetStress_FEM();
3598  /*--- Sigma xx ---*/
3599  Buffer_Send_Var[jPoint] = Stress[0];
3600  /*--- Sigma yy ---*/
3601  Buffer_Send_Res[jPoint] = Stress[1];
3602  /*--- Sigma xy ---*/
3603  Buffer_Send_Vol[jPoint] = Stress[2];
3604  jPoint++;
3605  }
3606  }
3607 
3608  /*--- Gather the data on the master node. ---*/
3609 
3610 #ifdef HAVE_MPI
3611  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3612  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3613  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3614 #else
3615  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3616  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3617  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
3618 #endif
3619 
3620  /*--- The master node unpacks and sorts this variable by global index ---*/
3621 
3622  if (rank == MASTER_NODE) {
3623  jPoint = 0; iVar = iVar_FEA_Stress;
3624  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3625  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3626 
3627  /*--- Get global index, then loop over each variable and store ---*/
3628 
3629  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3630  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3631  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3632  Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
3633  jPoint++;
3634  }
3635 
3636  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3637 
3638  jPoint = (iProcessor+1)*nBuffer_Scalar;
3639  }
3640  }
3641  }
3642 
3643  /*--- Communicate the FEM elasticity stresses (3D) - New elasticity solver---*/
3644 
3645  if ((Kind_Solver == FEM_ELASTICITY) && (geometry->GetnDim() == 3)) {
3646 
3647  /*--- Loop over this partition to collect the current variable ---*/
3648 
3649  jPoint = 0; su2double *Stress;
3650  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3651 
3652  /*--- Check for halos & write only if requested ---*/
3653 
3654  if (!Local_Halo[iPoint] || Wrt_Halo) {
3655 
3656  /*--- Load buffers with the three grid velocity components. ---*/
3657 
3658  Stress = solver[FEA_SOL]->node[iPoint]->GetStress_FEM();
3659  /*--- Sigma zz ---*/
3660  Buffer_Send_Var[jPoint] = Stress[3];
3661  /*--- Sigma xz ---*/
3662  Buffer_Send_Res[jPoint] = Stress[4];
3663  /*--- Sigma yz ---*/
3664  Buffer_Send_Vol[jPoint] = Stress[5];
3665  jPoint++;
3666  }
3667  }
3668 
3669  /*--- Gather the data on the master node. ---*/
3670 
3671 #ifdef HAVE_MPI
3672  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3673  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3674  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3675 #else
3676  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3677  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3678  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
3679 
3680 #endif
3681 
3682  /*--- The master node unpacks and sorts this variable by global index ---*/
3683 
3684  if (rank == MASTER_NODE) {
3685  jPoint = 0; iVar = iVar_FEA_Stress_3D;
3686  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3687  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3688 
3689  /*--- Get global index, then loop over each variable and store ---*/
3690 
3691  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3692  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3693  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3694  Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
3695  jPoint++;
3696  }
3697 
3698  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3699 
3700  jPoint = (iProcessor+1)*nBuffer_Scalar;
3701  }
3702  }
3703  }
3704 
3705 
3706  /*--- Communicate the Linear elasticity ---*/
3707 
3708  if ( Kind_Solver == FEM_ELASTICITY ) {
3709 
3710  /*--- Loop over this partition to collect the current variable ---*/
3711  jPoint = 0;
3712  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3713 
3714  /*--- Check for halos & write only if requested ---*/
3715 
3716  if (!Local_Halo[iPoint] || Wrt_Halo) {
3717 
3718  /*--- Load buffers with the temperature and laminar viscosity variables. ---*/
3719 
3720  Buffer_Send_Var[jPoint] = solver[FEA_SOL]->node[iPoint]->GetVonMises_Stress();
3721  jPoint++;
3722  }
3723  }
3724 
3725  /*--- Gather the data on the master node. ---*/
3726 
3727 #ifdef HAVE_MPI
3728  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3729 #else
3730  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3731 #endif
3732 
3733  /*--- The master node unpacks and sorts this variable by global index ---*/
3734 
3735  if (rank == MASTER_NODE) {
3736  jPoint = 0; iVar = iVar_FEA_Extra;
3737  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3738  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3739 
3740  /*--- Get global index, then loop over each variable and store ---*/
3741 
3742  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3743  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3744  jPoint++;
3745  }
3746 
3747  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3748 
3749  jPoint = (iProcessor+1)*nBuffer_Scalar;
3750  }
3751  }
3752  }
3753 
3754  if ((Kind_Solver == DISC_ADJ_FEM) && (config->GetFSI_Simulation())) {
3755  /*--- Loop over this partition to collect the current variable ---*/
3756 
3757  jPoint = 0;
3758  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3759 
3760  /*--- Check for halos & write only if requested ---*/
3761 
3762  if (!Local_Halo[iPoint] || Wrt_Halo) {
3763 
3764  /*--- Load buffers with the skin friction, heat transfer, y+ variables. ---*/
3765 
3766  Buffer_Send_Var[jPoint] = solver[ADJFEA_SOL]->node[iPoint]->GetGeometry_CrossTerm_Derivative(0);
3767  Buffer_Send_Res[jPoint] = solver[ADJFEA_SOL]->node[iPoint]->GetGeometry_CrossTerm_Derivative(1);
3768  if (geometry->GetnDim() == 3)
3769  Buffer_Send_Vol[jPoint] = solver[ADJFEA_SOL]->node[iPoint]->GetGeometry_CrossTerm_Derivative(2);
3770  jPoint++;
3771  }
3772  }
3773 
3774  /*--- Gather the data on the master node. ---*/
3775 
3776 #ifdef HAVE_MPI
3777  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3778  SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3779  if (nDim == 3)
3780  SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3781 #else
3782  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3783  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint];
3784  if (nDim == 3)
3785  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint];
3786 #endif
3787 
3788  /*--- The master node unpacks and sorts this variable by global index ---*/
3789 
3790  if (rank == MASTER_NODE) {
3791  jPoint = 0; iVar = iVar_FEA_Extra;
3792  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3793  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3794 
3795  /*--- Get global index, then loop over each variable and store ---*/
3796 
3797  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3798  Data[iVar+0][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3799  Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint];
3800  if (nDim == 3)
3801  Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint];
3802  jPoint++;
3803  }
3804 
3805  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3806 
3807  jPoint = (iProcessor+1)*nBuffer_Scalar;
3808  }
3809  }
3810  }
3811 
3812  if (config->GetExtraOutput()) {
3813 
3814  for (jVar = 0; jVar < nVar_Extra; jVar++) {
3815 
3816  /*--- Loop over this partition to collect the current variable ---*/
3817 
3818  jPoint = 0;
3819  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3820 
3821  /*--- Check for halos & write only if requested ---*/
3822 
3823  if (!Local_Halo[iPoint] || Wrt_Halo) {
3824 
3825  /*--- Get this variable into the temporary send buffer. ---*/
3826 
3827  if (Kind_Solver == RANS) {
3828  Buffer_Send_Var[jPoint] = solver[TURB_SOL]->OutputVariables[iPoint*nVar_Extra+jVar];
3829  }
3830  jPoint++;
3831 
3832  }
3833  }
3834 
3835  /*--- Gather the data on the master node. ---*/
3836 
3837 #ifdef HAVE_MPI
3838  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
3839 #else
3840  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
3841 #endif
3842 
3843  /*--- The master node unpacks and sorts this variable by global index ---*/
3844 
3845  if (rank == MASTER_NODE) {
3846  jPoint = 0; iVar = iVar_Extra;
3847  for (iProcessor = 0; iProcessor < size; iProcessor++) {
3848  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
3849 
3850  /*--- Get global index, then loop over each variable and store ---*/
3851 
3852  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
3853  Data[iVar+jVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
3854  jPoint++;
3855  }
3856 
3857  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
3858 
3859  jPoint = (iProcessor+1)*nBuffer_Scalar;
3860  }
3861  }
3862  }
3863  }
3864 
3865  }
3866 
3867  /*--- Immediately release the temporary buffers. ---*/
3868 
3869  delete [] Buffer_Send_Var;
3870  delete [] Buffer_Send_Res;
3871  delete [] Buffer_Send_Vol;
3872  delete [] Buffer_Send_GlobalIndex;
3873  if (rank == MASTER_NODE) {
3874  delete [] Buffer_Recv_nPoint;
3875  delete [] Buffer_Recv_Var;
3876  delete [] Buffer_Recv_Res;
3877  delete [] Buffer_Recv_Vol;
3878  delete [] Buffer_Recv_GlobalIndex;
3879  }
3880 
3881  /*--- Release memory needed for surface coefficients ---*/
3882 
3883  delete [] Local_Halo;
3884 
3885  if (((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) ||
3886  ((Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) {
3887  delete[] Aux_Frict_x; delete[] Aux_Frict_y; delete[] Aux_Frict_z;
3888  delete [] Aux_Heat; delete [] Aux_yPlus;
3889  }
3890  if (( Kind_Solver == ADJ_EULER ) ||
3891  ( Kind_Solver == ADJ_NAVIER_STOKES ) ||
3892  ( Kind_Solver == ADJ_RANS ) ||
3893  ( Kind_Solver == DISC_ADJ_EULER ) ||
3894  ( Kind_Solver == DISC_ADJ_NAVIER_STOKES ) ||
3895  ( Kind_Solver == DISC_ADJ_RANS )) {
3896  delete [] Aux_Sens;
3897  }
3898 
3899 }
3900 
3901 void COutput::MergeBaselineSolution(CConfig *config, CGeometry *geometry, CSolver *solver, unsigned short val_iZone) {
3902 
3903  /*--- Local variables needed on all processors ---*/
3904  unsigned short iVar;
3905  unsigned long iPoint = 0, jPoint = 0;
3906 
3907  unsigned short Kind_Solver = config->GetKind_Solver();
3908 
3909  nVar_Total = config->fields.size() - 1;
3910  //if(transp) nVar_Total += 1;
3911 
3912  /*--- Merge the solution either in serial or parallel. ---*/
3913 
3914 #ifndef HAVE_MPI
3915 
3916  /*--- In serial, the single process has access to all solution data,
3917  so it is simple to retrieve and store inside Solution_Data. ---*/
3918 
3919  unsigned short iMarker;
3920  unsigned long iVertex, nTotalPoints = 0;
3921  int SendRecv;
3922 
3923  /*--- First, create a structure to locate any periodic halo nodes ---*/
3924  int *Local_Halo = new int[geometry->GetnPoint()];
3925  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
3926  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
3927 
3928  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
3929  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
3930  SendRecv = config->GetMarker_All_SendRecv(iMarker);
3931  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
3932  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
3933  if ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
3934  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1) &&
3935  (SendRecv < 0)) {
3936  Local_Halo[iPoint] = false;
3937  }
3938  }
3939 
3940  }
3941  }
3942 
3943  /*--- Total number of points in the mesh (this might include periodic points). ---*/
3944 
3945  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
3946  if (!Local_Halo[iPoint]) nTotalPoints++;
3947 
3948  nGlobal_Poin = nTotalPoints;
3949  Data = new su2double*[nVar_Total];
3950  for (iVar = 0; iVar < nVar_Total; iVar++) {
3951  Data[iVar] = new su2double[nGlobal_Poin];
3952  }
3953 
3954  /*--- Loop over all points in the mesh, but only write data
3955  for nodes in the domain (ignore periodic halo nodes). ---*/
3956 
3957  jPoint = 0;
3958  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
3959  if (!Local_Halo[iPoint]) {
3960 
3961  /*--- Solution (first, and second system of equations) ---*/
3962 
3963  unsigned short jVar = 0;
3964  for (iVar = 0; iVar < nVar_Total; iVar++) {
3965  Data[jVar][jPoint] = solver->node[iPoint]->GetSolution(iVar);
3966  jVar++;
3967  }
3968  }
3969 
3970  /*--- Increment jPoint as the counter. We need this because iPoint
3971  may include halo nodes that we skip over during this loop. ---*/
3972 
3973  jPoint++;
3974 
3975  }
3976 
3977 #else
3978 
3979  /*--- MPI preprocessing ---*/
3980 
3981  int nProcessor = size, iProcessor;
3982 
3983  /*--- Local variables needed for merging with MPI ---*/
3984 
3985  unsigned long iVertex, iMarker;
3986  unsigned long Buffer_Send_nPoint[1], *Buffer_Recv_nPoint = NULL;
3987  unsigned long nLocalPoint = 0, MaxLocalPoint = 0;
3988  unsigned long iGlobal_Index = 0, nBuffer_Scalar = 0;
3989 
3990  int *Local_Halo = new int[geometry->GetnPoint()];
3991  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
3992  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
3993 
3994  bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
3995 
3996  /*--- Search all send/recv boundaries on this partition for any periodic
3997  nodes that were part of the original domain. We want to recover these
3998  for visualization purposes. ---*/
3999 
4000  if (Wrt_Halo) {
4001  nLocalPoint = geometry->GetnPoint();
4002  } else {
4003  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
4004  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
4005 
4006  /*--- Checking for less than or equal to the rank, because there may
4007  be some periodic halo nodes that send info to the same rank. ---*/
4008 
4009  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
4010  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
4011  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
4012  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
4013  if (isPeriodic) Local_Halo[iPoint] = false;
4014  }
4015  }
4016  }
4017 
4018  /*--- Sum total number of nodes that belong to the domain ---*/
4019 
4020  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
4021  if (Local_Halo[iPoint] == false)
4022  nLocalPoint++;
4023 
4024  }
4025  Buffer_Send_nPoint[0] = nLocalPoint;
4026 
4027  if (rank == MASTER_NODE) Buffer_Recv_nPoint = new unsigned long[nProcessor];
4028 
4029  SU2_MPI::Allreduce(&nLocalPoint, &MaxLocalPoint, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
4030  SU2_MPI::Gather(&Buffer_Send_nPoint, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nPoint, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
4031 
4032  nBuffer_Scalar = MaxLocalPoint;
4033 
4034  /*--- Send and Recv buffers. ---*/
4035 
4036  su2double *Buffer_Send_Var = new su2double[MaxLocalPoint];
4037  su2double *Buffer_Recv_Var = NULL;
4038 
4039  unsigned long *Buffer_Send_GlobalIndex = new unsigned long[MaxLocalPoint];
4040  unsigned long *Buffer_Recv_GlobalIndex = NULL;
4041 
4042  /*--- Prepare the receive buffers in the master node only. ---*/
4043  if (rank == MASTER_NODE) {
4044 
4045  Buffer_Recv_Var = new su2double[nProcessor*MaxLocalPoint];
4046  Buffer_Recv_GlobalIndex = new unsigned long[nProcessor*MaxLocalPoint];
4047 
4048  /*--- Sum total number of nodes to be written and allocate arrays ---*/
4049  nGlobal_Poin = 0;
4050  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
4051  nGlobal_Poin += Buffer_Recv_nPoint[iProcessor];
4052  }
4053  Data = new su2double*[nVar_Total];
4054  for (iVar = 0; iVar < nVar_Total; iVar++) {
4055  Data[iVar] = new su2double[nGlobal_Poin];
4056  }
4057 
4058  }
4059 
4060  /*--- Main communication routine. Loop over each variable that has
4061  been requested by the user and perform the MPI comm. Temporary
4062  1-D buffers are used to send the solution for each variable at all
4063  nodes on each partition to the master node. These are then unpacked
4064  by the master and sorted by global index in one large n-dim. array. ---*/
4065 
4066  for (iVar = 0; iVar < nVar_Total; iVar++) {
4067 
4068  /*--- Loop over this partition to collect the current variable ---*/
4069  jPoint = 0;
4070  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
4071 
4072  /*--- Check for halos and write only if requested ---*/
4073  if (!Local_Halo[iPoint] || Wrt_Halo) {
4074 
4075  /*--- Get this variable into the temporary send buffer. ---*/
4076  Buffer_Send_Var[jPoint] = solver->node[iPoint]->GetSolution(iVar);
4077 
4078  /*--- Only send/recv the volumes & global indices during the first loop ---*/
4079  if (iVar == 0) {
4080  Buffer_Send_GlobalIndex[jPoint] = geometry->node[iPoint]->GetGlobalIndex();
4081  }
4082  jPoint++;
4083  }
4084  }
4085 
4086  /*--- Gather the data on the master node. ---*/
4087 
4088  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
4089  if (iVar == 0) {
4090  SU2_MPI::Gather(Buffer_Send_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
4091  }
4092 
4093  /*--- The master node unpacks and sorts this variable by global index ---*/
4094  if (rank == MASTER_NODE) {
4095  jPoint = 0;
4096  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
4097  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
4098 
4099  /*--- Get global index, then loop over each variable and store ---*/
4100  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
4101  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
4102  jPoint++;
4103  }
4104  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
4105  jPoint = (iProcessor+1)*nBuffer_Scalar;
4106  }
4107  }
4108  }
4109 
4110  /*--- Immediately release the temporary buffers. ---*/
4111 
4112  delete [] Buffer_Send_Var;
4113  delete [] Buffer_Send_GlobalIndex;
4114  if (rank == MASTER_NODE) {
4115  delete [] Buffer_Recv_Var;
4116  delete [] Buffer_Recv_GlobalIndex;
4117  }
4118 
4119 #endif
4120 
4121  delete [] Local_Halo;
4122 
4123 }
4124 
4125 void COutput::SetRestart(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
4126 
4127  /*--- Local variables ---*/
4128 
4129  unsigned short nZone = geometry->GetnZone();
4130  unsigned short Kind_Solver = config->GetKind_Solver();
4131  unsigned short iVar, iDim, nDim = geometry->GetnDim();
4132  unsigned long iPoint, iExtIter = config->GetExtIter();
4133  bool grid_movement = config->GetGrid_Movement();
4134  bool dynamic_fem = (config->GetDynamic_Analysis() == DYNAMIC);
4135  bool fem = (config->GetKind_Solver() == FEM_ELASTICITY);
4136  bool disc_adj_fem = (config->GetKind_Solver() == DISC_ADJ_FEM);
4137  ofstream restart_file;
4138  ofstream meta_file;
4139  string filename, meta_filename;
4140  bool adjoint = config->GetContinuous_Adjoint() || config->GetDiscrete_Adjoint();
4141  bool dual_time = ((config->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
4142  (config->GetUnsteady_Simulation() == DT_STEPPING_2ND));
4143  bool transp = (config->GetnMarker_Transpiration() > 0);
4144 
4145  /*--- Retrieve filename from config ---*/
4146 
4147  if (((config->GetContinuous_Adjoint()) || (config->GetDiscrete_Adjoint())) && ((config->GetKind_Solver() != DISC_ADJ_FEM))) {
4148  filename = config->GetRestart_AdjFileName();
4149  filename = config->GetObjFunc_Extension(filename);
4150  } else if (fem) {
4151  filename = config->GetRestart_FEMFileName();
4152  } else if (disc_adj_fem){
4153  filename = config->GetRestart_AdjFEMFileName();
4154  } else {
4155  filename = config->GetRestart_FlowFileName();
4156  }
4157 
4158  /*--- Append the zone number if multizone problems ---*/
4159  if (nZone > 1)
4160  filename= config->GetMultizone_FileName(filename, val_iZone);
4161 
4162  /*--- Unsteady problems require an iteration number to be appended. ---*/
4163  if (config->GetUnsteady_Simulation() == HARMONIC_BALANCE) {
4164  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(config->GetiInst()));
4165  } else if (config->GetWrt_Unsteady()) {
4166  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(iExtIter));
4167  } else if ((fem || disc_adj_fem) && (config->GetWrt_Dynamic())) {
4168  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(iExtIter));
4169  }
4170 
4171  /*--- Open the restart file and write the solution. ---*/
4172 
4173  restart_file.open(filename.c_str(), ios::out);
4174  restart_file.precision(15);
4175 
4176  /*--- Write the header line based on the particular solver ----*/
4177 
4178  restart_file << "\"PointID\"";
4179 
4180  /*--- Mesh coordinates are always written to the restart first ---*/
4181 
4182  if (nDim == 2) {
4183  restart_file << "\t\"x\"\t\"y\"";
4184  } else {
4185  restart_file << "\t\"x\"\t\"y\"\t\"z\"";
4186  }
4187 
4188  for (iVar = 0; iVar < nVar_Consv; iVar++) {
4189  if (( Kind_Solver == FEM_ELASTICITY ) || ( Kind_Solver == DISC_ADJ_FEM))
4190  restart_file << "\t\"Displacement_" << iVar+1<<"\"";
4191  else
4192  restart_file << "\t\"Conservative_" << iVar+1<<"\"";
4193  }
4194 
4195  if (!config->GetLow_MemoryOutput()) {
4196 
4197  if (config->GetWrt_Limiters()) {
4198  for (iVar = 0; iVar < nVar_Consv; iVar++) {
4199  restart_file << "\t\"Limiter_" << iVar+1<<"\"";
4200  }
4201  }
4202  if (config->GetWrt_Residuals()) {
4203  for (iVar = 0; iVar < nVar_Consv; iVar++) {
4204  restart_file << "\t\"Residual_" << iVar+1<<"\"";
4205  }
4206  }
4207 
4208  /*--- Mesh velocities for dynamic mesh cases ---*/
4209 
4210  if (grid_movement && !fem) {
4211  if (nDim == 2) {
4212  restart_file << "\t\"Grid_Velx\"\t\"Grid_Vely\"";
4213  } else {
4214  restart_file << "\t\"Grid_Velx\"\t\"Grid_Vely\"\t\"Grid_Velz\"";
4215  }
4216  }
4217 
4218  if ((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
4219  if ((config->GetOutput_FileFormat() == PARAVIEW) || (config->GetOutput_FileFormat() == PARAVIEW_BINARY)) {
4220  restart_file << "\t\"Pressure\"\t\"Temperature\"\t\"Pressure_Coefficient\"\t\"Mach\"";
4221  } else
4222  restart_file << "\t\"Pressure\"\t\"Temperature\"\t\"C<sub>p</sub>\"\t\"Mach\"";
4223  }
4224 
4225  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
4226  if ((config->GetOutput_FileFormat() == PARAVIEW) || (config->GetOutput_FileFormat() == PARAVIEW_BINARY)) {
4227  if (nDim == 2) restart_file << "\t\"Laminar_Viscosity\"\t\"Skin_Friction_Coefficient_X\"\t\"Skin_Friction_Coefficient_Y\"\t\"Heat_Flux\"\t\"Y_Plus\"";
4228  if (nDim == 3) restart_file << "\t\"Laminar_Viscosity\"\t\"Skin_Friction_Coefficient_X\"\t\"Skin_Friction_Coefficient_Y\"\t\"Skin_Friction_Coefficient_Z\"\t\"Heat_Flux\"\t\"Y_Plus\"";
4229  } else {
4230  if (nDim == 2) restart_file << "\t\"<greek>m</greek>\"\t\"C<sub>f</sub>_x\"\t\"C<sub>f</sub>_y\"\t\"h\"\t\"y<sup>+</sup>\"";
4231  if (nDim == 3) restart_file << "\t\"<greek>m</greek>\"\t\"C<sub>f</sub>_x\"\t\"C<sub>f</sub>_y\"\t\"C<sub>f</sub>_z\"\t\"h\"\t\"y<sup>+</sup>\"";
4232  }
4233  }
4234 
4235  if (Kind_Solver == RANS) {
4236  if ((config->GetOutput_FileFormat() == PARAVIEW) || (config->GetOutput_FileFormat() == PARAVIEW_BINARY)) {
4237  restart_file << "\t\"Eddy_Viscosity\"";
4238  } else
4239  restart_file << "\t\"<greek>m</greek><sub>t</sub>\"";
4240  }
4241 
4242  if (config->GetWrt_SharpEdges()) {
4243  if (((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS))) {
4244  restart_file << "\t\"Sharp_Edge_Dist\"";
4245  }
4246  }
4247 
4248  if ((Kind_Solver == ADJ_EULER ) ||
4249  (Kind_Solver == ADJ_NAVIER_STOKES ) ||
4250  (Kind_Solver == ADJ_RANS ) ) {
4251  restart_file << "\t\"Surface_Sensitivity\"\t\"Solution_Sensor\"";
4252  }
4253  if (( Kind_Solver == DISC_ADJ_EULER ) ||
4254  ( Kind_Solver == DISC_ADJ_NAVIER_STOKES ) ||
4255  ( Kind_Solver == DISC_ADJ_RANS )) {
4256  restart_file << "\t\"Surface_Sensitivity\"\t\"Sensitivity_x\"\t\"Sensitivity_y\"";
4257  if (geometry->GetnDim() == 3) {
4258  restart_file << "\t\"Sensitivity_z\"";
4259  }
4260  }
4261 
4262  if (transp && ((Kind_Solver == DISC_ADJ_EULER) ||
4263  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
4264  (Kind_Solver == DISC_ADJ_RANS))) {
4265  restart_file << "\t\"Sensitivity_Transp\"";
4266  }
4267 
4268  if (Kind_Solver == FEM_ELASTICITY) {
4269  if (!dynamic_fem) {
4270  if (geometry->GetnDim() == 2)
4271  restart_file << "\t\"Sxx\"\t\"Syy\"\t\"Sxy\"\t\"Von_Mises_Stress\"";
4272  if (geometry->GetnDim() == 3)
4273  restart_file << "\t\"Sxx\"\t\"Syy\"\t\"Sxy\"\t\"Szz\"\t\"Sxz\"\t\"Syz\"\t\"Von_Mises_Stress\"";
4274  }
4275  else if (dynamic_fem) {
4276  if (geometry->GetnDim() == 2) {
4277  restart_file << "\t\"Velocity_1\"\t\"Velocity_2\"\t\"Acceleration_1\"\t\"Acceleration_2\"";
4278  restart_file << "\t\"Sxx\"\t\"Syy\"\t\"Sxy\"\t\"Von_Mises_Stress\"";
4279  }
4280  if (geometry->GetnDim() == 3) {
4281  restart_file << "\t\"Velocity_1\"\t\"Velocity_2\"\t\"Velocity_3\"\t\"Acceleration_1\"\t\"Acceleration_2\"\t\"Acceleration_3\"";
4282  restart_file << "\t\"Sxx\"\t\"Syy\"\t\"Sxy\"\t\"Szz\"\t\"Sxz\"\t\"Syz\"\t\"Von_Mises_Stress\"";
4283  }
4284  }
4285  }
4286 
4287  if ((Kind_Solver == DISC_ADJ_FEM) && (config->GetFSI_Simulation())){
4288  if (geometry->GetnDim() == 2)
4289  restart_file << "\t\"CrossTerm_1\"\t\"CrossTerm_2\"";
4290  if (geometry->GetnDim() == 3)
4291  restart_file << "\t\"CrossTerm_1\"\t\"CrossTerm_2\"\t\"CrossTerm_3\"";
4292  }
4293 
4294 
4295  if (config->GetExtraOutput()) {
4296  string *headings = NULL;
4297  //if (Kind_Solver == RANS) {
4298  headings = solver[TURB_SOL]->OutputHeadingNames;
4299  //}
4300 
4301  for (iVar = 0; iVar < nVar_Extra; iVar++) {
4302  if (headings == NULL) {
4303  restart_file << "\t\"ExtraOutput_" << iVar+1<<"\"";
4304  } else {
4305  restart_file << "\t\""<< headings[iVar] <<"\"";
4306  }
4307  }
4308  }
4309  }
4310 
4311  restart_file << "\n";
4312 
4313  /*--- Write the restart file ---*/
4314 
4315  /*--- Determine whether or not the FEM solver is used, which decides the
4316  type of geometry classes that are instantiated. ---*/
4317  bool fem_solver = ((config->GetKind_Solver() == FEM_EULER) ||
4318  (config->GetKind_Solver() == FEM_NAVIER_STOKES) ||
4319  (config->GetKind_Solver() == FEM_RANS) ||
4320  (config->GetKind_Solver() == FEM_LES));
4321 
4322  unsigned long nPointTotal = 0;
4323  if ( fem_solver ) {
4324  nPointTotal = solver[FLOW_SOL]->GetnDOFsGlobal();
4325  } else {
4326  nPointTotal = geometry->GetGlobal_nPointDomain();
4327  }
4328 
4329  for (iPoint = 0; iPoint < nPointTotal; iPoint++) {
4330 
4331  /*--- Index of the point ---*/
4332  restart_file << iPoint << "\t";
4333 
4334  /*--- Write the grid coordinates first ---*/
4335  for (iDim = 0; iDim < nDim; iDim++) {
4336  restart_file << scientific << Coords[iDim][iPoint] << "\t";
4337  }
4338 
4339  /*--- Loop over the variables and write the values to file ---*/
4340  for (iVar = 0; iVar < nVar_Total; iVar++) {
4341  restart_file << scientific << Data[iVar][iPoint] << "\t";
4342  }
4343  restart_file << "\n";
4344  }
4345 
4346  /*--- Write the general header and flow conditions ----*/
4347 
4348  if (dual_time)
4349  restart_file <<"EXT_ITER= " << config->GetExtIter() + 1 << endl;
4350  else
4351  restart_file <<"EXT_ITER= " << config->GetExtIter() + config->GetExtIter_OffSet() + 1 << endl;
4352  restart_file <<"AOA= " << config->GetAoA() - config->GetAoA_Offset() << endl;
4353  restart_file <<"SIDESLIP_ANGLE= " << config->GetAoS() - config->GetAoS_Offset() << endl;
4354  restart_file <<"INITIAL_BCTHRUST= " << config->GetInitial_BCThrust() << endl;
4355  restart_file <<"DCD_DCL_VALUE= " << config->GetdCD_dCL() << endl;
4356  restart_file <<"DCMX_DCL_VALUE= " << config->GetdCMx_dCL() << endl;
4357  restart_file <<"DCMY_DCL_VALUE= " << config->GetdCMy_dCL() << endl;
4358  restart_file <<"DCMZ_DCL_VALUE= " << config->GetdCMz_dCL() << endl;
4359  if (adjoint) restart_file << "SENS_AOA=" << solver[ADJFLOW_SOL]->GetTotal_Sens_AoA() * PI_NUMBER / 180.0 << endl;
4360 
4361  /*--- Close the data portion of the restart file. ---*/
4362 
4363  restart_file.close();
4364 
4365 }
4366 
4368 
4369  unsigned short iDim, nDim = geometry->GetnDim();
4370 
4371  /*--- The master node alone owns all data found in this routine. ---*/
4372 
4373  if (rank == MASTER_NODE) {
4374 
4375  /*--- Deallocate memory for coordinate data ---*/
4376 
4377  for (iDim = 0; iDim < nDim; iDim++) {
4378  delete [] Coords[iDim];
4379  }
4380  delete [] Coords;
4381  }
4382 }
4383 
4384 void COutput::DeallocateConnectivity(CConfig *config, CGeometry *geometry, bool surf_sol) {
4385 
4386  /*--- The master node alone owns all data found in this routine. ---*/
4387  if (rank == MASTER_NODE) {
4388 
4389  /*--- Deallocate memory for connectivity data ---*/
4390  if (surf_sol) {
4391  if (nGlobal_Line > 0 && Conn_Line != NULL) delete [] Conn_Line;
4392  if (nGlobal_BoundTria > 0 && Conn_BoundTria != NULL) delete [] Conn_BoundTria;
4393  if (nGlobal_BoundQuad > 0 && Conn_BoundQuad != NULL) delete [] Conn_BoundQuad;
4394  }
4395  else {
4396  if (nGlobal_Tria > 0 && Conn_Tria != NULL) delete [] Conn_Tria;
4397  if (nGlobal_Quad > 0 && Conn_Quad != NULL) delete [] Conn_Quad;
4398  if (nGlobal_Tetr > 0 && Conn_Tetr != NULL) delete [] Conn_Tetr;
4399  if (nGlobal_Hexa > 0 && Conn_Hexa != NULL) delete [] Conn_Hexa;
4400  if (nGlobal_Pris > 0 && Conn_Pris != NULL) delete [] Conn_Pris;
4401  if (nGlobal_Pyra > 0 && Conn_Pyra != NULL) delete [] Conn_Pyra;
4402 
4403  }
4404 
4405  }
4406 }
4407 
4409 
4410  /*--- The master node alone owns all data found in this routine. ---*/
4411  if (rank == MASTER_NODE) {
4412 
4413  /*--- Deallocate memory for solution data ---*/
4414  for (unsigned short iVar = 0; iVar < nVar_Total; iVar++) {
4415  delete [] Data[iVar];
4416  }
4417  delete [] Data;
4418 
4419  }
4420 }
4421 
4422 void COutput::SetConvHistory_Header(ofstream *ConvHist_file, CConfig *config, unsigned short val_iZone, unsigned short val_iInst) {
4423  char cstr[200], buffer[50], turb_resid[1000], adj_turb_resid[1000];
4424  unsigned short iMarker_Monitoring;
4425  string Monitoring_Tag, monitoring_coeff, aeroelastic_coeff, turbo_coeff;
4426 
4427  bool rotating_frame = config->GetRotating_Frame();
4428  bool aeroelastic = config->GetAeroelastic_Simulation();
4429  bool equiv_area = config->GetEquivArea();
4430  bool buffet = (config->GetBuffet_Monitoring() || config->GetKind_ObjFunc() == BUFFET_SENSOR);
4431  bool engine = ((config->GetnMarker_EngineInflow() != 0) || (config->GetnMarker_EngineExhaust() != 0));
4432  bool actuator_disk = ((config->GetnMarker_ActDiskInlet() != 0) || (config->GetnMarker_ActDiskOutlet() != 0));
4433  bool turbulent = ((config->GetKind_Solver() == RANS) || (config->GetKind_Solver() == ADJ_RANS) ||
4434  (config->GetKind_Solver() == DISC_ADJ_RANS));
4435  bool cont_adj = config->GetContinuous_Adjoint();
4436  bool disc_adj = config->GetDiscrete_Adjoint();
4437  bool frozen_visc = (cont_adj && config->GetFrozen_Visc_Cont()) ||( disc_adj && config->GetFrozen_Visc_Disc());
4438  bool inv_design = (config->GetInvDesign_Cp() || config->GetInvDesign_HeatFlux());
4439 
4440  bool output_surface = (config->GetnMarker_Analyze() != 0);
4441  bool output_comboObj = (config->GetnObj() > 1);
4442  bool output_per_surface = config->GetWrt_Surface();
4443  bool turbo = config->GetBoolTurbomachinery();
4444  unsigned short direct_diff = config->GetDirectDiff();
4445 
4446  bool compressible = (config->GetKind_Regime() == COMPRESSIBLE);
4447  bool incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE);
4448  bool incload = config->GetIncrementalLoad();
4449 
4450  bool transp = (config->GetnMarker_Transpiration() > 0); /* flag for if transpiration BC is being used */
4451 
4452  bool thermal = false; /* Flag for whether to print heat flux values */
4453  bool weakly_coupled_heat = config->GetWeakly_Coupled_Heat();
4454 
4455  if (config->GetKind_Solver() == RANS || config->GetKind_Solver() == NAVIER_STOKES) {
4456  thermal = true;
4457  }
4458 
4459  /*--- Write file name with extension ---*/
4460  string filename = config->GetConv_FileName();
4461  if(config->GetnZone() > 1){
4462  filename = config->GetMultizone_HistoryFileName(filename, val_iZone);
4463  }
4464  if(config->GetnTimeInstances() > 1){
4465  filename = config->GetMultiInstance_HistoryFileName(filename, val_iInst);
4466  }
4467  strcpy (cstr, filename.data());
4468 
4469  if (config->GetWrt_Unsteady() && config->GetRestart()) {
4470  long iExtIter = config->GetUnst_RestartIter();
4471  if (SU2_TYPE::Int(iExtIter) < 10) SPRINTF (buffer, "_0000%d", SU2_TYPE::Int(iExtIter));
4472  if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d", SU2_TYPE::Int(iExtIter));
4473  if ((SU2_TYPE::Int(iExtIter) >= 100) && (SU2_TYPE::Int(iExtIter) < 1000)) SPRINTF (buffer, "_00%d", SU2_TYPE::Int(iExtIter));
4474  if ((SU2_TYPE::Int(iExtIter) >= 1000) && (SU2_TYPE::Int(iExtIter) < 10000)) SPRINTF (buffer, "_0%d", SU2_TYPE::Int(iExtIter));
4475  if (SU2_TYPE::Int(iExtIter) >= 10000) SPRINTF (buffer, "_%d", SU2_TYPE::Int(iExtIter));
4476  strcat(cstr, buffer);
4477  }
4478 
4479  if ((config->GetOutput_FileFormat() == TECPLOT) ||
4480  (config->GetOutput_FileFormat() == FIELDVIEW)) SPRINTF (buffer, ".dat");
4481  else if ((config->GetOutput_FileFormat() == TECPLOT_BINARY) ||
4482  (config->GetOutput_FileFormat() == FIELDVIEW_BINARY)) SPRINTF (buffer, ".plt");
4483  else if ((config->GetOutput_FileFormat() == PARAVIEW) || (config->GetOutput_FileFormat() == PARAVIEW_BINARY)) SPRINTF (buffer, ".csv");
4484  strcat(cstr, buffer);
4485 
4486  ConvHist_file->open(cstr, ios::out);
4487  ConvHist_file->precision(15);
4488 
4489  /*--- Begin of the header ---*/
4490 
4491  char begin[]= "\"Iteration\"";
4492 
4493  /*--- Header for the coefficients ---*/
4494 
4495  char flow_coeff[]= ",\"CL\",\"CD\",\"CSF\",\"CMx\",\"CMy\",\"CMz\",\"CFx\",\"CFy\",\"CFz\",\"CL/CD\",\"AoA\",\"Custom_ObjFunc\"";
4496  char heat_coeff[]= ",\"HeatFlux_Total\",\"HeatFlux_Maximum\",\"Temperature_Total\"";
4497  char equivalent_area_coeff[]= ",\"CEquivArea\",\"CNearFieldOF\"";
4498  char buffet_coeff[]= ",\"Buffet_Metric\"";
4499  char engine_coeff[]= ",\"NetThrust\",\"Power\",\"AeroCDrag\",\"SolidCDrag\",\"Radial_Distortion\",\"Circumferential_Distortion\"";
4500  char rotating_frame_coeff[]= ",\"CMerit\",\"CT\",\"CQ\"";
4501  char fem_coeff[]= ",\"VM_Stress\",\"Force_Coeff\"";
4502  char fem_incload[]= ",\"IncLoad\"";
4503  char adj_coeff[]= ",\"Sens_Geo\",\"Sens_Mach\",\"Sens_AoA\",\"Sens_Press\",\"Sens_Temp\",\"Sens_AoS\"";
4504  char adj_inc_coeff[]=",\"Sens_Geo\",\"Sens_Vin\",\"Sens_Pout\",\"Sens_Temp\"";
4505  char adj_turbo_coeff[]=",\"Sens_Geo\",\"Sens_PressOut\",\"Sens_TotTempIn\"";
4506  char surface_outputs[]= ",\"Avg_MassFlow\",\"Avg_Mach\",\"Avg_Temp\",\"Avg_Press\",\"Avg_Density\",\"Avg_Enthalpy\",\"Avg_NormalVel\",\"Uniformity\",\"Secondary_Strength\",\"Momentum_Distortion\",\"Secondary_Over_Uniformity\",\"Avg_TotalTemp\",\"Avg_TotalPress\",\"Pressure_Drop\"";
4507  char Cp_inverse_design[]= ",\"Cp_Diff\"";
4508  char Heat_inverse_design[]= ",\"HeatFlux_Diff\"";
4509  char d_flow_coeff[] = ",\"D(CL)\",\"D(CD)\",\"D(CSF)\",\"D(CMx)\",\"D(CMy)\",\"D(CMz)\",\"D(CFx)\",\"D(CFy)\",\"D(CFz)\",\"D(CL/CD)\",\"D(Custom_ObjFunc)\"";
4510  char d_thermal_coeff[] = ",\"D(HeatFlux_Total)\",\"D(HeatFlux_Maximum)\"";
4511  char d_engine[] = ",\"D(NetThrust)\",\"D(Power)\",\"D(AeroCDrag)\",\"D(SolidCDrag)\",\"D(Radial_Distortion)\",\"D(Circumferential_Distortion)\"";
4512  char d_turbo_coeff[] = ",\"D(TotalPressureLoss_0)\",\"D(FlowAngleOut_0)\",\"D(TotalEfficency)\",\"D(TotalStaticEfficiency)\", \"D(EntropyGen)\"";
4513  char d_surface_outputs[]= ",\"D(Uniformity)\",\"D(Secondary_Strength)\",\"D(Momentum_Distortion)\",\"D(Secondary_Over_Uniformity)\",\"D(Pressure_Drop)\"";
4514  char transp_coeff[]= ", \"Cmu\"";
4515 
4516  /*--- Find the markers being monitored and create a header for them ---*/
4517 
4518  for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) {
4519  Monitoring_Tag = config->GetMarker_Monitoring_TagBound(iMarker_Monitoring);
4520  monitoring_coeff += ",\"CL_" + Monitoring_Tag + "\"";
4521  monitoring_coeff += ",\"CD_" + Monitoring_Tag + "\"";
4522  monitoring_coeff += ",\"CSF_" + Monitoring_Tag + "\"";
4523  monitoring_coeff += ",\"CL/CD_" + Monitoring_Tag + "\"";
4524  monitoring_coeff += ",\"CFx_" + Monitoring_Tag + "\"";
4525  monitoring_coeff += ",\"CFy_" + Monitoring_Tag + "\"";
4526  monitoring_coeff += ",\"CFz_" + Monitoring_Tag + "\"";
4527  monitoring_coeff += ",\"CMx_" + Monitoring_Tag + "\"";
4528  monitoring_coeff += ",\"CMy_" + Monitoring_Tag + "\"";
4529  monitoring_coeff += ",\"CMz_" + Monitoring_Tag + "\"";
4530  if(buffet) monitoring_coeff += ",\"Buffet_Metric_" + Monitoring_Tag + "\"";
4531  aeroelastic_coeff += ",\"plunge_" + Monitoring_Tag + "\"";
4532  aeroelastic_coeff += ",\"pitch_" + Monitoring_Tag + "\"";
4533  }
4534 
4535  if (turbo){
4536  for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_TurboPerformance(); iMarker_Monitoring++) {
4537 
4538  stringstream tag;
4539  tag << iMarker_Monitoring + 1;
4540 
4541  turbo_coeff += ",\"TotalPressureLoss_" + tag.str() + "\"";
4542  turbo_coeff += ",\"KineticEnergyLoss_" + tag.str() + "\"";
4543  turbo_coeff += ",\"EntropyGen_" + tag.str() + "\"";
4544  turbo_coeff += ",\"EulerianWork_" + tag.str() + "\"";
4545  turbo_coeff += ",\"PressureRatio_" + tag.str() + "\"";
4546  turbo_coeff += ",\"FlowAngleIn_" + tag.str() + "\"";
4547  turbo_coeff += ",\"FlowAngleOut_" + tag.str() + "\"";
4548  turbo_coeff += ",\"AbsFlowAngleIn_" + tag.str() + "\"";
4549  turbo_coeff += ",\"AbsFlowAngleOut_" + tag.str() + "\"";
4550  turbo_coeff += ",\"MassFlowIn_" + tag.str() + "\"";
4551  turbo_coeff += ",\"MassFlowOut_" + tag.str() + "\"";
4552  turbo_coeff += ",\"MachIn_" + tag.str() + "\"";
4553  turbo_coeff += ",\"MachOut_" + tag.str() + "\"";
4554  // different from zero only in multi-zone computation
4555  turbo_coeff += ",\"TotalEfficiency_" + tag.str() + "\"";
4556  turbo_coeff += ",\"TotalStaticEfficiency_" + tag.str() + "\"";
4557 
4558  }
4559  }
4560 
4561  char combo_obj[] = ",\"ComboObj\"";
4562 
4563  /*--- Header for the residuals ---*/
4564 
4565  char flow_resid[]= ",\"Res_Flow[0]\",\"Res_Flow[1]\",\"Res_Flow[2]\",\"Res_Flow[3]\",\"Res_Flow[4]\"";
4566  char adj_flow_resid[]= ",\"Res_AdjFlow[0]\",\"Res_AdjFlow[1]\",\"Res_AdjFlow[2]\",\"Res_AdjFlow[3]\",\"Res_AdjFlow[4]\"";
4567  switch (config->GetKind_Turb_Model()) {
4568  case SA:case SA_NEG:case SA_E: case SA_COMP: case SA_E_COMP:
4569  SPRINTF (turb_resid, ",\"Res_Turb[0]\"");
4570  break;
4571  case SST: SPRINTF (turb_resid, ",\"Res_Turb[0]\",\"Res_Turb[1]\""); break;
4572  }
4573  switch (config->GetKind_Turb_Model()) {
4574  case SA:case SA_NEG:case SA_E: case SA_COMP: case SA_E_COMP:
4575  SPRINTF (adj_turb_resid, ",\"Res_AdjTurb[0]\"");
4576  break;
4577  case SST: SPRINTF (adj_turb_resid, ",\"Res_AdjTurb[0]\",\"Res_AdjTurb[1]\""); break;
4578  }
4579  char fem_resid[]= ",\"Res_FEM[0]\",\"Res_FEM[1]\",\"Res_FEM[2]\"";
4580  char heat_resid[]= ",\"Res_Heat\"";
4581 
4582  /*--- End of the header ---*/
4583 
4584  char end[]= ",\"Linear_Solver_Iterations\",\"CFL_Number\",\"Time(min)\"\n";
4585  char endfea[]= ",\"Linear_Solver_Iterations\",\"Time(min)\"\n";
4586 
4587  if ((config->GetOutput_FileFormat() == TECPLOT) ||
4588  (config->GetOutput_FileFormat() == TECPLOT_BINARY) ||
4589  (config->GetOutput_FileFormat() == FIELDVIEW) ||
4590  (config->GetOutput_FileFormat() == FIELDVIEW_BINARY)) {
4591  ConvHist_file[0] << "TITLE = \"SU2 Simulation\"" << endl;
4592  ConvHist_file[0] << "VARIABLES = ";
4593  }
4594 
4595  /*--- Write the header, case depending ---*/
4596 
4597  switch (config->GetKind_Solver()) {
4598 
4599  case EULER : case NAVIER_STOKES: case RANS :
4600  case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_RANS : case FEM_LES:
4601  ConvHist_file[0] << begin;
4602  if (!turbo) ConvHist_file[0] << flow_coeff;
4603  if (transp) ConvHist_file[0] << transp_coeff;
4604  if (buffet) ConvHist_file[0] << buffet_coeff;
4605  if (turbo) ConvHist_file[0] << turbo_coeff;
4606  if (thermal && !turbo) ConvHist_file[0] << heat_coeff;
4607  if (equiv_area) ConvHist_file[0] << equivalent_area_coeff;
4608  if (engine || actuator_disk) ConvHist_file[0] << engine_coeff;
4609  if (inv_design) {
4610  ConvHist_file[0] << Cp_inverse_design;
4611  if (thermal && !turbo) ConvHist_file[0] << Heat_inverse_design;
4612  }
4613  if (rotating_frame && !turbo) ConvHist_file[0] << rotating_frame_coeff;
4614  ConvHist_file[0] << flow_resid;
4615  if (turbulent) ConvHist_file[0] << turb_resid;
4616  if (weakly_coupled_heat) ConvHist_file[0] << heat_resid;
4617  if (aeroelastic) ConvHist_file[0] << aeroelastic_coeff;
4618  if (output_per_surface) ConvHist_file[0] << monitoring_coeff;
4619  if (output_surface) ConvHist_file[0] << surface_outputs;
4620  if (direct_diff != NO_DERIVATIVE) {
4621  if (!turbo) ConvHist_file[0] << d_flow_coeff;
4622  else ConvHist_file[0] << d_turbo_coeff;
4623  if (engine || actuator_disk) ConvHist_file[0] << d_engine;
4624  if (thermal) ConvHist_file[0] << d_thermal_coeff;
4625  if (output_surface) ConvHist_file[0] << d_surface_outputs;
4626  }
4627  if (output_comboObj) ConvHist_file[0] << combo_obj;
4628  ConvHist_file[0] << end;
4629 
4630  break;
4631 
4632  case ADJ_EULER : case ADJ_NAVIER_STOKES : case ADJ_RANS:
4634  if (!turbo) {
4635  if (compressible) {
4636  ConvHist_file[0] << begin << adj_coeff << adj_flow_resid;
4637  }
4638  if (incompressible) {
4639  ConvHist_file[0] << begin << adj_inc_coeff << adj_flow_resid;
4640  }
4641  }
4642  else ConvHist_file[0] << begin << adj_turbo_coeff << adj_flow_resid;
4643  if ((turbulent) && (!frozen_visc)) ConvHist_file[0] << adj_turb_resid;
4644  ConvHist_file[0] << end;
4645  break;
4646 
4647  case HEAT_EQUATION_FVM:
4648  ConvHist_file[0] << begin << heat_coeff;
4649  ConvHist_file[0] << heat_resid << end;
4650  break;
4651 
4652  case FEM_ELASTICITY:
4653  ConvHist_file[0] << begin << fem_coeff;
4654  if (incload) ConvHist_file[0] << fem_incload;
4655  ConvHist_file[0] << fem_resid << endfea;
4656  break;
4657 
4658  case DISC_ADJ_FEM:
4659  ConvHist_file[0] << begin << fem_coeff;
4660  ConvHist_file[0] << fem_resid << endfea;
4661  break;
4662 
4663  }
4664 
4665  if (config->GetOutput_FileFormat() == TECPLOT ||
4666  config->GetOutput_FileFormat() == TECPLOT_BINARY ||
4667  config->GetOutput_FileFormat() == FIELDVIEW ||
4668  config->GetOutput_FileFormat() == FIELDVIEW_BINARY) {
4669  ConvHist_file[0] << "ZONE T= \"Convergence history\"" << endl;
4670  }
4671 
4672 }
4673 
4674 
4675 void COutput::SetConvHistory_Body(ofstream *ConvHist_file,
4676  CGeometry ****geometry,
4677  CSolver *****solver_container,
4678  CConfig **config,
4679  CIntegration ****integration,
4680  bool DualTime_Iteration,
4681  su2double timeused,
4682  unsigned short val_iZone,
4683  unsigned short val_iInst) {
4684 
4685  bool output_surface = (config[val_iZone]->GetnMarker_Analyze() != 0);
4686  bool output_comboObj = (config[val_iZone]->GetnObj() > 1);
4687  bool fluid_structure = (config[val_iZone]->GetFSI_Simulation());
4688  bool fea = ((config[val_iZone]->GetKind_Solver()== FEM_ELASTICITY)||(config[val_iZone]->GetKind_Solver()== DISC_ADJ_FEM));
4689  unsigned long iIntIter = config[val_iZone]->GetIntIter();
4690  unsigned long iExtIter = config[val_iZone]->GetExtIter();
4691  unsigned short FinestMesh = config[val_iZone]->GetFinestMesh();
4692  unsigned short nZone = config[val_iZone]->GetnZone();
4693  unsigned short nInst = config[val_iZone]->GetnTimeInstances();
4694  bool cont_adj = config[val_iZone]->GetContinuous_Adjoint();
4695  bool disc_adj = config[val_iZone]->GetDiscrete_Adjoint();
4696  bool energy = config[val_iZone]->GetEnergy_Equation();
4697  bool incload = config[val_iZone]->GetIncrementalLoad();
4698  bool output_files = true;
4699 
4700  bool compressible = (config[val_iZone]->GetKind_Regime() == COMPRESSIBLE);
4701  bool incompressible = (config[val_iZone]->GetKind_Regime() == INCOMPRESSIBLE);
4702 
4703  if (!disc_adj && !cont_adj && !DualTime_Iteration) {
4704 
4705  if ((config[val_iZone]->GetFixed_CL_Mode()) &&
4706  (config[val_iZone]->GetnExtIter()-config[val_iZone]->GetIter_dCL_dAlpha() - 1 < iExtIter)) {
4707  output_files = false;
4708  }
4709 
4710  if (fea || fluid_structure) output_files = false;
4711 
4712  /*--- We need to evaluate some of the objective functions to write the value on the history file ---*/
4713 
4714  if (((iExtIter % (config[val_iZone]->GetWrt_Sol_Freq())) == 0) ||
4715  ((!config[val_iZone]->GetFixed_CL_Mode()) && (iExtIter == (config[val_iZone]->GetnExtIter()-1))) ||
4716  /*--- If CL mode we need to compute the complete solution at two very particular iterations ---*/
4717  ((config[val_iZone]->GetFixed_CL_Mode()) && (iExtIter == (config[val_iZone]->GetnExtIter()-2))) ||
4718  ((config[val_iZone]->GetFixed_CL_Mode()) && (config[val_iZone]->GetnExtIter()-config[val_iZone]->GetIter_dCL_dAlpha() - 1 == iExtIter))) {
4719 
4720 
4721  if ((rank == MASTER_NODE) && output_files) cout << endl << "------------------------ Evaluate Special Output ------------------------";
4722 
4723  switch (config[val_iZone]->GetKind_Solver()) {
4724 
4725  case EULER: case NAVIER_STOKES: case RANS:
4726 
4727  /*--- For specific applications, evaluate and plot the surface. ---*/
4728 
4729  if (config[val_iZone]->GetnMarker_Analyze() != 0) {
4730  SpecialOutput_AnalyzeSurface(solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL],
4731  geometry[val_iZone][val_iInst][MESH_0], config[val_iZone], output_files);
4732  }
4733 
4734  /*--- For specific applications, evaluate and plot the surface. ---*/
4735 
4736  if ((config[val_iZone]->GetnMarker_Analyze() != 0) && compressible) {
4737  SpecialOutput_Distortion(solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL],
4738  geometry[val_iZone][val_iInst][MESH_0], config[val_iZone], output_files);
4739  }
4740 
4741  /*--- For specific applications, evaluate and plot the equivalent area. ---*/
4742 
4743  if (config[val_iZone]->GetnMarker_NearFieldBound() != 0) {
4744  SpecialOutput_SonicBoom(solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL],
4745  geometry[val_iZone][val_iInst][MESH_0], config[val_iZone], output_files);
4746  }
4747 
4748  /*--- For specific applications, evaluate and plot the cp coefficent at different stations. ---*/
4749 
4750  if (config[val_iZone]->GetPlot_Section_Forces()) {
4751  SpecialOutput_SpanLoad(solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL],
4752  geometry[val_iZone][val_iInst][MESH_0], config[val_iZone], output_files);
4753  }
4754 
4755  break;
4756  }
4757 
4758  /*--- Output a file with the forces breakdown. ---*/
4759 
4760  if (config[val_iZone]->GetUnsteady_Simulation() == HARMONIC_BALANCE) {
4761  SpecialOutput_HarmonicBalance(solver_container, geometry, config, val_iInst, nInst, output_files);
4762  }
4763 
4764  /*--- Compute span-wise values file for turbomachinery. ---*/
4765 
4766  if (config[val_iZone]->GetBoolTurbomachinery()) {
4767  SpecialOutput_Turbo(solver_container, geometry, config, val_iZone, output_files);
4768  }
4769 
4770  /*--- Output a file with the forces breakdown. ---*/
4771 
4772  SpecialOutput_ForcesBreakdown(solver_container, geometry, config, val_iZone, output_files);
4773 
4774  if ((rank == MASTER_NODE) && output_files) cout << "-------------------------------------------------------------------------" << endl << endl;
4775 
4776  }
4777 
4778  }
4779 
4780  /*--- Output using only the master node ---*/
4781 
4782  if (rank == MASTER_NODE) {
4783 
4784  /*-- Compute the total objective if a "combo" objective is used ---*/
4785 
4786  if (output_comboObj) {
4787  solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->SetTotal_ComboObj(0.0);
4788  switch (config[val_iZone]->GetKind_Solver()) {
4789  case EULER: case NAVIER_STOKES: case RANS:
4790  solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->Evaluate_ObjFunc(config[val_iZone]);
4791  break;
4792  }
4793  }
4794 
4795  unsigned long ExtIter_OffSet = config[val_iZone]->GetExtIter_OffSet();
4796  if (config[val_iZone]->GetUnsteady_Simulation() == DT_STEPPING_1ST ||
4797  config[val_iZone]->GetUnsteady_Simulation() == DT_STEPPING_2ND)
4798  ExtIter_OffSet = 0;
4799 
4800  /*--- WARNING: These buffers have hard-coded lengths. Note that you
4801  may have to adjust them to be larger if adding more entries. ---*/
4802 
4803  char begin[1000], direct_coeff[1000], heat_coeff[1000], equivalent_area_coeff[1000], engine_coeff[1000], rotating_frame_coeff[1000], Cp_inverse_design[1000], Heat_inverse_design[1000], surface_coeff[1000], aeroelastic_coeff[1000], monitoring_coeff[10000], buffet_coeff[1000],
4804  adjoint_coeff[1000], flow_resid[1000], adj_flow_resid[1000], turb_resid[1000], trans_resid[1000],
4805  adj_turb_resid[1000],
4806  begin_fem[1000], fem_coeff[1000], heat_resid[1000], combo_obj[1000],
4807  fem_resid[1000], end[1000], end_fem[1000], surface_outputs[1000], d_surface_outputs[1000], d_direct_coeff[1000], turbo_coeff[10000],
4808  transp_coeff[1000];
4809 
4810 
4811  su2double dummy = 0.0, *Coord;
4812  unsigned short iVar, iMarker_Monitoring;
4813 
4814  unsigned long LinSolvIter = 0, iPointMaxResid;
4815  su2double timeiter = timeused/su2double(iExtIter+1);
4816 
4817  unsigned short nDim = geometry[val_iZone][val_iInst][FinestMesh]->GetnDim();
4818 
4819 
4820  bool rotating_frame = config[val_iZone]->GetRotating_Frame();
4821  bool aeroelastic = config[val_iZone]->GetAeroelastic_Simulation();
4822  bool equiv_area = config[val_iZone]->GetEquivArea();
4823  bool engine = ((config[val_iZone]->GetnMarker_EngineInflow() != 0) || (config[val_iZone]->GetnMarker_EngineExhaust() != 0));
4824  bool actuator_disk = ((config[val_iZone]->GetnMarker_ActDiskInlet() != 0) || (config[val_iZone]->GetnMarker_ActDiskOutlet() != 0));
4825  bool inv_design = (config[val_iZone]->GetInvDesign_Cp() || config[val_iZone]->GetInvDesign_HeatFlux());
4826  bool transition = (config[val_iZone]->GetKind_Trans_Model() == LM);
4827  bool thermal = (config[val_iZone]->GetKind_Solver() == RANS || config[val_iZone]->GetKind_Solver() == NAVIER_STOKES);
4828  bool turbulent = ((config[val_iZone]->GetKind_Solver() == RANS) || (config[val_iZone]->GetKind_Solver() == ADJ_RANS) ||
4829  (config[val_iZone]->GetKind_Solver() == DISC_ADJ_RANS));
4830  bool adjoint = cont_adj || disc_adj;
4831  bool frozen_visc = (cont_adj && config[val_iZone]->GetFrozen_Visc_Cont()) ||( disc_adj && config[val_iZone]->GetFrozen_Visc_Disc());
4832  bool heat = ((config[val_iZone]->GetKind_Solver() == HEAT_EQUATION_FVM) || (config[val_iZone]->GetWeakly_Coupled_Heat()));
4833  bool weakly_coupled_heat = config[val_iZone]->GetWeakly_Coupled_Heat();
4834  bool flow = (config[val_iZone]->GetKind_Solver() == EULER) || (config[val_iZone]->GetKind_Solver() == NAVIER_STOKES) ||
4835  (config[val_iZone]->GetKind_Solver() == RANS) || (config[val_iZone]->GetKind_Solver() == FEM_EULER) || (config[val_iZone]->GetKind_Solver() == FEM_NAVIER_STOKES) || (config[val_iZone]->GetKind_Solver() == FEM_RANS) || (config[val_iZone]->GetKind_Solver() == FEM_LES) || (config[val_iZone]->GetKind_Solver() == ADJ_EULER) ||
4836  (config[val_iZone]->GetKind_Solver() == ADJ_NAVIER_STOKES) || (config[val_iZone]->GetKind_Solver() == ADJ_RANS);
4837  bool buffet = (config[val_iZone]->GetBuffet_Monitoring() || config[val_iZone]->GetKind_ObjFunc() == BUFFET_SENSOR);
4838 
4839  bool fem = ((config[val_iZone]->GetKind_Solver() == FEM_ELASTICITY) || // FEM structural solver.
4840  (config[val_iZone]->GetKind_Solver() == DISC_ADJ_FEM));
4841  bool linear_analysis = (config[val_iZone]->GetGeometricConditions() == SMALL_DEFORMATIONS); // Linear analysis.
4842  bool nonlinear_analysis = (config[val_iZone]->GetGeometricConditions() == LARGE_DEFORMATIONS); // Nonlinear analysis.
4843  bool fsi = (config[val_iZone]->GetFSI_Simulation()); // FEM structural solver.
4844  bool discadj_fem = (config[val_iZone]->GetKind_Solver() == DISC_ADJ_FEM);
4845 
4846  bool transp = (config[val_iZone]->GetnMarker_Transpiration() > 0); /* flag for if transpiration BC is being used */
4847 
4848  bool turbo = config[val_iZone]->GetBoolTurbomachinery();
4849 
4850  unsigned short nTurboPerf = config[val_iZone]->GetnMarker_TurboPerformance();
4851 
4852  bool output_per_surface = config[val_iZone]->GetWrt_Surface();
4853 
4854  unsigned short direct_diff = config[val_iZone]->GetDirectDiff();
4855 
4856  long ExtraHeatOutputZone = config[val_iZone]->GetExtraHeatOutputZone() - 1;
4857  bool extra_heat_output = false;
4858  su2double Extra_Total_Heat = 0.0;
4859  //su2double Extra_Total_Temperature = 0.0;
4860  su2double Extra_Heat_Residual = 0.0;
4861 
4862  if (ExtraHeatOutputZone > -1) {
4863  if (ExtraHeatOutputZone > nZone) {
4864  SU2_MPI::Error("Error in output routine: Extra output zone number exceeds total number of zones.", CURRENT_FUNCTION);
4865  }
4866  else if ((config[ExtraHeatOutputZone]->GetKind_Solver() != HEAT_EQUATION_FVM)) {
4867  SU2_MPI::Error("Error in output routine: No heat solver in extra output zone.", CURRENT_FUNCTION);
4868  }
4869  else {
4870  extra_heat_output = true;
4871  }
4872  }
4873 
4874  /*--- Initialize variables to store information from all domains (direct solution) ---*/
4875 
4876  su2double Total_CL = 0.0, Total_CD = 0.0, Total_CSF = 0.0, Total_CMx = 0.0, Total_CMy = 0.0, Total_CMz = 0.0, Total_CEff = 0.0,
4877  Total_CEquivArea = 0.0, Total_CNearFieldOF = 0.0, Total_CFx = 0.0, Total_CFy = 0.0, Total_CFz = 0.0, Total_CMerit = 0.0,
4878  Total_CT = 0.0, Total_CQ = 0.0,
4879  Total_Heat = 0.0, Total_MaxHeat = 0.0, Total_Temperature = 0.0, Total_Custom_ObjFunc = 0.0,
4880  Total_ComboObj = 0.0, Total_NetThrust = 0.0, Total_Power = 0.0, Total_AeroCD = 0.0, Total_SolidCD = 0.0, Total_IDR = 0.0, Total_IDC = 0.0,
4881  Total_AoA = 0.0, Total_Buffet_Metric = 0.0;
4882  su2double Surface_MassFlow = 0.0, Surface_Mach = 0.0, Surface_Temperature = 0.0, Surface_Pressure = 0.0, Surface_Density = 0.0, Surface_Enthalpy = 0.0, Surface_NormalVelocity = 0.0, Surface_TotalTemperature = 0.0, Surface_TotalPressure = 0.0, Surface_Uniformity = 0.0, Surface_SecondaryStrength = 0.0,Surface_MomentumDistortion = 0.0, Surface_SecondOverUniform = 0.0, Surface_PressureDrop = 0.0;
4883 
4884  su2double Total_ForceCoeff = 0.0, Total_VMStress = 0.0, Total_IncLoad = 0.0;
4885  su2double Total_SensE = 0.0, Total_SensNu = 0.0;
4886  su2double Total_Cmu = 0.0;
4887 
4888  unsigned short iSpan;
4889 
4890  /*--- Initialize variables to store information from all domains (adjoint solution) ---*/
4891  su2double Total_Sens_Geo = 0.0, Total_Sens_Mach = 0.0, Total_Sens_AoA = 0.0;
4892  su2double Total_Sens_Press = 0.0, Total_Sens_Temp = 0.0;
4893 
4894  su2double Total_Sens_BPressure = 0.0;
4895  su2double Total_Sens_ModVel = 0.0;
4896 
4897  /*--- Initialize variables to store information from all domains (direct differentiation) ---*/
4898  su2double D_Total_CL = 0.0, D_Total_CD = 0.0, D_Total_CSF = 0.0, D_Total_CMx = 0.0, D_Total_CMy = 0.0, D_Total_CMz = 0.0, D_Total_CEff = 0.0, D_Total_CFx = 0.0,
4899  D_Total_CFy = 0.0, D_Total_CFz = 0.0, D_Total_NetThrust = 0.0, D_Total_Power = 0.0, D_Total_AeroCD = 0.0, D_Total_SolidCD = 0.0, D_Total_IDR = 0.0, D_Total_IDC = 0.0, D_Total_Custom_ObjFunc = 0.0, D_Total_Heat = 0.0, D_Total_MaxHeat = 0.0,
4900  D_TotalPressure_Loss = 0.0, D_FlowAngle_Out = 0.0, D_TotalStaticEfficiency = 0.0,
4901  D_TotalTotalEfficiency = 0.0, D_EntropyGen = 0.0,
4902  D_Surface_Uniformity = 0.0, D_Surface_SecondaryStrength = 0.0, D_Surface_MomentumDistortion = 0.0, D_Surface_SecondOverUniform = 0.0, D_Surface_PressureDrop = 0.0;
4903 
4904  /*--- Residual arrays ---*/
4905  su2double *residual_flow = NULL,
4906  *residual_turbulent = NULL,
4907  *residual_transition = NULL;
4908  su2double *residual_adjflow = NULL,
4909  *residual_adjturbulent = NULL;
4910  su2double *residual_fea = NULL;
4911  su2double *residual_fem = NULL;
4912  su2double *residual_heat = NULL;
4913 
4914  /*--- Coefficients Monitored arrays ---*/
4915  su2double *aeroelastic_plunge = NULL,
4916  *aeroelastic_pitch = NULL,
4917  *Surface_CL = NULL,
4918  *Surface_CD = NULL,
4919  *Surface_CSF = NULL,
4920  *Surface_CEff = NULL,
4921  *Surface_CFx = NULL,
4922  *Surface_CFy = NULL,
4923  *Surface_CFz = NULL,
4924  *Surface_CMx = NULL,
4925  *Surface_CMy = NULL,
4926  *Surface_CMz = NULL,
4927  *Surface_Buffet_Metric = NULL;
4928 
4929  /*--- Initialize number of variables ---*/
4930  unsigned short nVar_Flow = 0, nVar_Turb = 0,
4931  nVar_Trans = 0, nVar_Heat = 0,
4932  nVar_AdjFlow = 0, nVar_AdjTurb = 0,
4933  nVar_FEM = 0;
4934 
4935  /*--- Direct problem variables ---*/
4936  if (compressible) nVar_Flow = nDim+2; else nVar_Flow = nDim+2;
4937  if (turbulent) {
4938  switch (config[val_iZone]->GetKind_Turb_Model()) {
4939  case SA: case SA_NEG: case SA_E: case SA_E_COMP: case SA_COMP: nVar_Turb = 1; break;
4940  case SST: nVar_Turb = 2; break;
4941  }
4942  }
4943  if (transition) nVar_Trans = 2;
4944  if (heat) nVar_Heat = 1;
4945 
4946  if (fem) {
4947  if (linear_analysis) nVar_FEM = nDim;
4948  if (nonlinear_analysis) nVar_FEM = 3;
4949 
4950  if (config[val_iZone]->GetKind_Solver() == DISC_ADJ_FEM) nVar_FEM = nDim;
4951 
4952  }
4953 
4954  /*--- Adjoint problem variables ---*/
4955  if (compressible) nVar_AdjFlow = nDim+2; else nVar_AdjFlow = nDim+2;
4956  if (turbulent) {
4957  switch (config[val_iZone]->GetKind_Turb_Model()) {
4958  case SA: case SA_NEG: case SA_E: case SA_E_COMP: case SA_COMP: nVar_AdjTurb = 1; break;
4959  case SST: nVar_AdjTurb = 2; break;
4960  }
4961  }
4962 
4963  /*--- Allocate memory for the residual ---*/
4964  residual_flow = new su2double[nVar_Flow];
4965  residual_turbulent = new su2double[nVar_Turb];
4966  residual_transition = new su2double[nVar_Trans];
4967  residual_heat = new su2double[nVar_Heat];
4968  residual_fem = new su2double[nVar_FEM];
4969 
4970  residual_adjflow = new su2double[nVar_AdjFlow];
4971  residual_adjturbulent = new su2double[nVar_AdjTurb];
4972 
4973  /*--- Allocate memory for the coefficients being monitored ---*/
4974  aeroelastic_plunge = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4975  aeroelastic_pitch = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4976  Surface_CL = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4977  Surface_CD = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4978  Surface_CSF = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4979  Surface_CEff = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4980  Surface_CFx = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4981  Surface_CFy = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4982  Surface_CFz = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4983  Surface_CMx = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4984  Surface_CMy = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4985  Surface_CMz = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4986  if(buffet) Surface_Buffet_Metric = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
4987 
4988  /*--- Write information from nodes ---*/
4989 
4990  switch (config[val_iZone]->GetKind_Solver()) {
4991 
4992  case EULER: case NAVIER_STOKES: case RANS:
4993  case FEM_EULER: case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES:
4994  case ADJ_EULER: case ADJ_NAVIER_STOKES: case ADJ_RANS:
4996 
4997  /*--- Flow solution coefficients ---*/
4998 
4999  Total_CL = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CL();
5000  Total_CD = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CD();
5001  Total_CSF = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CSF();
5002  Total_CEff = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CEff();
5003  Total_CMx = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CMx();
5004  Total_CMy = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CMy();
5005  Total_CMz = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CMz();
5006  Total_CFx = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CFx();
5007  Total_CFy = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CFy();
5008  Total_CFz = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CFz();
5009  Total_ComboObj = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_ComboObj();
5010  Total_AoA = config[val_iZone]->GetAoA() - config[val_iZone]->GetAoA_Offset();
5011  Total_Custom_ObjFunc = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_Custom_ObjFunc();
5012  Total_Cmu = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_Cmu();
5013 
5014  if (thermal) {
5015  Total_Heat = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_HeatFlux();
5016  Total_MaxHeat = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_MaxHeatFlux();
5017  Total_Temperature = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_AvgTemperature();
5018 
5019  if(weakly_coupled_heat) {
5020  Total_Heat = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_HeatFlux();
5021  Total_MaxHeat = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_MaxHeatFlux();
5022  Total_Temperature = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_AvgTemperature();
5023  }
5024  }
5025 
5026  if(buffet){
5027  Total_Buffet_Metric = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_Buffet_Metric();
5028  }
5029 
5030  if (direct_diff != NO_DERIVATIVE) {
5031  D_Total_CL = SU2_TYPE::GetDerivative(Total_CL);
5032  D_Total_CD = SU2_TYPE::GetDerivative(Total_CD);
5033  D_Total_CSF = SU2_TYPE::GetDerivative(Total_CSF);
5034  D_Total_CEff = SU2_TYPE::GetDerivative(Total_CEff);
5035  D_Total_CMx = SU2_TYPE::GetDerivative(Total_CMx);
5036  D_Total_CMy = SU2_TYPE::GetDerivative(Total_CMy);
5037  D_Total_CMz = SU2_TYPE::GetDerivative(Total_CMz);
5038  D_Total_CFx = SU2_TYPE::GetDerivative(Total_CFx);
5039  D_Total_CFy = SU2_TYPE::GetDerivative(Total_CFy);
5040  D_Total_CFz = SU2_TYPE::GetDerivative(Total_CFz);
5041  D_Total_Custom_ObjFunc = SU2_TYPE::GetDerivative(Total_Custom_ObjFunc);
5042 
5043  if (thermal) {
5044  D_Total_Heat = SU2_TYPE::GetDerivative(Total_Heat);
5045  D_Total_MaxHeat = SU2_TYPE::GetDerivative(Total_MaxHeat);
5046  //Davg Temp
5047  }
5048 
5049  if (engine || actuator_disk) {
5050  D_Total_NetThrust = SU2_TYPE::GetDerivative(Total_NetThrust);
5051  D_Total_Power = SU2_TYPE::GetDerivative(Total_Power);
5052  D_Total_AeroCD = SU2_TYPE::GetDerivative(Total_AeroCD);
5053  D_Total_SolidCD = SU2_TYPE::GetDerivative(Total_SolidCD);
5054  D_Total_IDR = SU2_TYPE::GetDerivative(Total_IDR);
5055  D_Total_IDC = SU2_TYPE::GetDerivative(Total_IDC);
5056  }
5057 
5058  }
5059 
5060  if (equiv_area) {
5061  Total_CEquivArea = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CEquivArea();
5062  Total_CNearFieldOF = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CNearFieldOF();
5063 
5064  Total_CEquivArea = config[val_iZone]->GetWeightCd()*Total_CD + (1.0-config[val_iZone]->GetWeightCd())*Total_CEquivArea;
5065  Total_CNearFieldOF = config[val_iZone]->GetWeightCd()*Total_CD + (1.0-config[val_iZone]->GetWeightCd())*Total_CNearFieldOF;
5066  }
5067 
5068  if (engine || actuator_disk) {
5069  Total_NetThrust = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_NetThrust();
5070  Total_Power = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_Power();
5071  Total_AeroCD = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_AeroCD();
5072  Total_SolidCD = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_SolidCD();
5073  Total_IDR = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_IDR();
5074  Total_IDC = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_IDC();
5075  }
5076 
5077  if (rotating_frame) {
5078  Total_CT = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CT();
5079  Total_CQ = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CQ();
5080  Total_CMerit = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CMerit();
5081  }
5082 
5083  if (aeroelastic) {
5084  /*--- Look over the markers being monitored and get the desired values ---*/
5085  for (iMarker_Monitoring = 0; iMarker_Monitoring < config[ZONE_0]->GetnMarker_Monitoring(); iMarker_Monitoring++) {
5086  aeroelastic_plunge[iMarker_Monitoring] = config[val_iZone]->GetAeroelastic_plunge(iMarker_Monitoring);
5087  aeroelastic_pitch[iMarker_Monitoring] = config[val_iZone]->GetAeroelastic_pitch(iMarker_Monitoring);
5088  }
5089  }
5090 
5091  if (output_per_surface) {
5092  /*--- Look over the markers being monitored and get the desired values ---*/
5093  for (iMarker_Monitoring = 0; iMarker_Monitoring < config[ZONE_0]->GetnMarker_Monitoring(); iMarker_Monitoring++) {
5094  Surface_CL[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CL(iMarker_Monitoring);
5095  Surface_CD[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CD(iMarker_Monitoring);
5096  Surface_CSF[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CSF(iMarker_Monitoring);
5097  Surface_CEff[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CEff(iMarker_Monitoring);
5098  Surface_CFx[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CFx(iMarker_Monitoring);
5099  Surface_CFy[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CFy(iMarker_Monitoring);
5100  Surface_CFz[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CFz(iMarker_Monitoring);
5101  Surface_CMx[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CMx(iMarker_Monitoring);
5102  Surface_CMy[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CMy(iMarker_Monitoring);
5103  Surface_CMz[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CMz(iMarker_Monitoring);
5104 
5105  if(buffet) Surface_Buffet_Metric[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_Buffet_Metric(iMarker_Monitoring);
5106  }
5107  }
5108 
5109  if (turbo) {
5110  /*--- Loop over the nMarker of turboperformance and get the desired values ---*/
5111  for (iMarker_Monitoring = 0; iMarker_Monitoring < nTurboPerf; iMarker_Monitoring++) {
5112  for(iSpan=0; iSpan<nSpanWiseSections+1; iSpan++){
5113  if ((iMarker_Monitoring == 0) && (direct_diff != NO_DERIVATIVE)){
5114  D_TotalPressure_Loss = SU2_TYPE::GetDerivative(TotalPressureLoss[iMarker_Monitoring][iSpan]);
5115  D_FlowAngle_Out = 180.0/PI_NUMBER*SU2_TYPE::GetDerivative(FlowAngleOut[iMarker_Monitoring][iSpan]);
5116  }
5117  }
5118  }
5119  if (direct_diff != NO_DERIVATIVE){
5120  D_TotalStaticEfficiency = SU2_TYPE::GetDerivative(TotalStaticEfficiency[nTurboPerf-1][nSpanWiseSections]);
5121  D_TotalTotalEfficiency = SU2_TYPE::GetDerivative(TotalTotalEfficiency[nTurboPerf-1][nSpanWiseSections]);
5122  D_EntropyGen = SU2_TYPE::GetDerivative(EntropyGen[nTurboPerf-1][nSpanWiseSections]);
5123  }
5124  }
5125 
5126  /*--- Get flux-averaged values at the specified surface ---*/
5127 
5128  if (output_surface) {
5129 
5130  unsigned short iMarker_Analyze = 0;
5131  Surface_MassFlow = config[ZONE_0]->GetSurface_MassFlow(iMarker_Analyze);
5132  Surface_Mach = config[ZONE_0]->GetSurface_Mach(iMarker_Analyze);
5133  Surface_Temperature = config[ZONE_0]->GetSurface_Temperature(iMarker_Analyze);
5134  Surface_Pressure = config[ZONE_0]->GetSurface_Pressure(iMarker_Analyze);
5135  Surface_Density = config[ZONE_0]->GetSurface_Density(iMarker_Analyze);
5136  Surface_Enthalpy = config[ZONE_0]->GetSurface_Enthalpy(iMarker_Analyze);
5137  Surface_NormalVelocity = config[ZONE_0]->GetSurface_NormalVelocity(iMarker_Analyze);
5138  Surface_Uniformity = config[ZONE_0]->GetSurface_Uniformity(iMarker_Analyze);
5139  Surface_SecondaryStrength = config[ZONE_0]->GetSurface_SecondaryStrength(iMarker_Analyze);
5140  Surface_MomentumDistortion = config[ZONE_0]->GetSurface_MomentumDistortion(iMarker_Analyze);
5141  Surface_SecondOverUniform = config[ZONE_0]->GetSurface_SecondOverUniform(iMarker_Analyze);
5142  Surface_TotalTemperature = config[ZONE_0]->GetSurface_TotalTemperature(iMarker_Analyze);
5143  Surface_TotalPressure = config[ZONE_0]->GetSurface_TotalPressure(iMarker_Analyze);
5144  Surface_PressureDrop = config[ZONE_0]->GetSurface_PressureDrop(iMarker_Analyze);
5145 
5146  if (direct_diff != NO_DERIVATIVE){
5147  D_Surface_Uniformity = SU2_TYPE::GetDerivative(Surface_Uniformity);
5148  D_Surface_SecondaryStrength = SU2_TYPE::GetDerivative(Surface_SecondaryStrength);
5149  D_Surface_MomentumDistortion = SU2_TYPE::GetDerivative(Surface_MomentumDistortion);
5150  D_Surface_SecondOverUniform = SU2_TYPE::GetDerivative(Surface_SecondOverUniform);
5151  D_Surface_PressureDrop = SU2_TYPE::GetDerivative(Surface_PressureDrop);
5152  }
5153  }
5154 
5155  /*--- Flow Residuals ---*/
5156 
5157  for (iVar = 0; iVar < nVar_Flow; iVar++)
5158  residual_flow[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetRes_RMS(iVar);
5159 
5160  /*--- Turbulent residual ---*/
5161 
5162  if (turbulent) {
5163  for (iVar = 0; iVar < nVar_Turb; iVar++)
5164  residual_turbulent[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][TURB_SOL]->GetRes_RMS(iVar);
5165  }
5166 
5167  if (weakly_coupled_heat) {
5168  for (iVar = 0; iVar < nVar_Heat; iVar++) {
5169  residual_heat[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetRes_RMS(iVar);
5170  }
5171 
5172  }
5173 
5174  /*--- Transition residual ---*/
5175 
5176  if (transition) {
5177  for (iVar = 0; iVar < nVar_Trans; iVar++)
5178  residual_transition[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][TRANS_SOL]->GetRes_RMS(iVar);
5179  }
5180 
5181 
5182  /*--- FEA residual ---*/
5183  // if (fluid_structure) {
5184  // for (iVar = 0; iVar < nVar_FEA; iVar++)
5185  // residual_fea[iVar] = solver_container[ZONE_0][FinestMesh][FEA_SOL]->GetRes_RMS(iVar);
5186  // }
5187 
5188  /*--- Iterations of the linear solver ---*/
5189 
5190  LinSolvIter = (unsigned long) solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetIterLinSolver();
5191 
5192  /*--- Adjoint solver ---*/
5193 
5194  if (adjoint) {
5195 
5196  /*--- Adjoint solution coefficients ---*/
5197 
5198  Total_Sens_Geo = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_Geo();
5199  Total_Sens_Mach = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_Mach();
5200  Total_Sens_AoA = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_AoA() * PI_NUMBER / 180.0;
5201  Total_Sens_Press = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_Press();
5202  Total_Sens_Temp = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_Temp();
5203  Total_Sens_BPressure = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_BPress();
5204  Total_Sens_ModVel = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_ModVel();
5205 
5206  /*--- Adjoint flow residuals ---*/
5207 
5208  for (iVar = 0; iVar < nVar_AdjFlow; iVar++) {
5209  residual_adjflow[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetRes_RMS(iVar);
5210  }
5211 
5212  /*--- Adjoint turbulent residuals ---*/
5213 
5214  if (turbulent) {
5215  if (!frozen_visc) {
5216  for (iVar = 0; iVar < nVar_AdjTurb; iVar++)
5217  residual_adjturbulent[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][ADJTURB_SOL]->GetRes_RMS(iVar);
5218  }
5219  }
5220 
5221  }
5222 
5223  break;
5224 
5225 
5226  case HEAT_EQUATION_FVM:
5227 
5228  /*--- Heat coefficients ---*/
5229 
5230  Total_Heat = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_HeatFlux();
5231  Total_MaxHeat = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_MaxHeatFlux();
5232  Total_Temperature = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_AvgTemperature();
5233 
5234  /*--- Heat Residuals ---*/
5235 
5236  for (iVar = 0; iVar < nVar_Heat; iVar++) {
5237  residual_heat[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetRes_RMS(iVar);
5238  }
5239 
5240  break;
5241 
5242  case FEM_ELASTICITY:
5243 
5244  /*--- FEM coefficients -- As of now, this is the Von Mises Stress ---*/
5245 
5246  Total_VMStress = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetTotal_CFEA();
5247 
5248  Total_ForceCoeff = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetForceCoeff();
5249 
5250  Total_IncLoad = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetLoad_Increment();
5251 
5252  LinSolvIter = (unsigned long) solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetIterLinSolver();
5253 
5254  /*--- Residuals: ---*/
5255  /*--- Linear analysis: RMS of the displacements in the nDim coordinates ---*/
5256  /*--- Nonlinear analysis: UTOL, RTOL and DTOL (defined in the Postprocessing function) ---*/
5257 
5258  if (linear_analysis) {
5259  for (iVar = 0; iVar < nVar_FEM; iVar++) {
5260  residual_fem[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetRes_RMS(iVar);
5261  }
5262  }
5263  else if (nonlinear_analysis) {
5264  for (iVar = 0; iVar < nVar_FEM; iVar++) {
5265  residual_fem[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetRes_FEM(iVar);
5266  }
5267  }
5268 
5269  break;
5270 
5271  case DISC_ADJ_FEM:
5272 
5273  /*--- FEM coefficients -- As of now, this is the Von Mises Stress ---*/
5274 
5275  Total_VMStress = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetTotal_CFEA();
5276 
5277  /*--- Residuals: ---*/
5278  /*--- Linear analysis: RMS of the displacements in the nDim coordinates ---*/
5279  /*--- Nonlinear analysis: UTOL, RTOL and DTOL (defined in the Postprocessing function) ---*/
5280  for (iVar = 0; iVar < nVar_FEM; iVar++) {
5281  residual_fem[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][ADJFEA_SOL]->GetRes_RMS(iVar);
5282  }
5283 
5284  break;
5285 
5286 
5287  }
5288 
5289  if (extra_heat_output) {
5290  Extra_Total_Heat = solver_container[ExtraHeatOutputZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_HeatFlux();
5291  //Extra_Total_Temperature = solver_container[ExtraHeatOutputZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_Temperature();
5292  Extra_Heat_Residual = log10(solver_container[ExtraHeatOutputZone][val_iInst][FinestMesh][HEAT_SOL]->GetRes_RMS(0));
5293  }
5294 
5295  /*--- Header frequency ---*/
5296 
5297  bool Unsteady = ((config[val_iZone]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
5298  (config[val_iZone]->GetUnsteady_Simulation() == DT_STEPPING_2ND));
5299  bool In_NoDualTime = (!DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0));
5300  bool In_DualTime_0 = (DualTime_Iteration && (iIntIter % config[val_iZone]->GetWrt_Con_Freq_DualTime() == 0));
5301  bool In_DualTime_1 = (!DualTime_Iteration && Unsteady);
5302  bool In_DualTime_2 = (Unsteady && DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0));
5303  bool In_DualTime_3 = (Unsteady && !DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0));
5304 
5305  /*--- Header frequency: analogy for dynamic structural analysis ---*/
5306  /*--- DualTime_Iteration is a bool we receive, which is true if it comes from FEM_StructuralIteration and false from SU2_CFD ---*/
5307  /*--- We maintain the name, as it is an input of the function ---*/
5308  /*--- The function GetWrt_Con_Freq_DualTime should be modified to be able to define different frequencies ---*/
5309  /*--- dynamic determines if the problem is, or not, time dependent ---*/
5310  bool dynamic = (config[val_iZone]->GetDynamic_Analysis() == DYNAMIC); // Dynamic simulations.
5311  bool In_NoDynamic = (!DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0));
5312  bool In_Dynamic_0 = (DualTime_Iteration && (iIntIter % config[val_iZone]->GetWrt_Con_Freq_DualTime() == 0));
5313  bool In_Dynamic_1 = (!DualTime_Iteration && nonlinear_analysis);
5314  bool In_Dynamic_2 = (nonlinear_analysis && DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0));
5315  bool In_Dynamic_3 = (nonlinear_analysis && !DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0));
5316 
5317  bool write_heads;
5318  if (Unsteady) write_heads = (iIntIter == 0);
5319  else write_heads = (((iExtIter % (config[val_iZone]->GetWrt_Con_Freq()*40)) == 0));
5320 
5321  bool write_turbo = (((iExtIter % (config[val_iZone]->GetWrt_Con_Freq()*40)) == 0) || (iExtIter == (config[val_iZone]->GetnExtIter() -1)));
5322 
5323  /*--- Analogous for dynamic problems (as of now I separate the problems, it may be worthy to do all together later on ---*/
5324  bool write_heads_FEM;
5325  if (nonlinear_analysis) write_heads_FEM = (iIntIter == 0);
5326  else write_heads_FEM = (((iExtIter % (config[val_iZone]->GetWrt_Con_Freq()*40)) == 0));
5327 
5328  if ( (!fem && ((In_NoDualTime || In_DualTime_0 || In_DualTime_1) && (In_NoDualTime || In_DualTime_2 || In_DualTime_3))) ||
5329  (fem && ( (In_NoDynamic || In_Dynamic_0 || In_Dynamic_1) && (In_NoDynamic || In_Dynamic_2 || In_Dynamic_3)))
5330  ) {
5331 
5332 
5333  /*--- Prepare the history file output, note that the dual
5334  time output don't write to the history file ---*/
5335  if (!DualTime_Iteration) {
5336 
5337  /*--- Write the begining of the history file ---*/
5338  SPRINTF(begin, "%12d", SU2_TYPE::Int(iExtIter+ExtIter_OffSet));
5339 
5340  /*--- Write the end of the history file ---*/
5341  SPRINTF (end, ", %12.10f, %12.10f, %12.10f\n", su2double(LinSolvIter), config[val_iZone]->GetCFL(MESH_0), timeused/60.0);
5342 
5343  /*--- Write the solution and residual of the history file ---*/
5344  switch (config[val_iZone]->GetKind_Solver()) {
5345 
5346  case EULER : case NAVIER_STOKES: case RANS:
5347  case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES:
5348  case ADJ_EULER: case ADJ_NAVIER_STOKES: case ADJ_RANS: case DISC_ADJ_EULER:
5350 
5351  /*--- Direct coefficients ---*/
5352  SPRINTF (direct_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e",
5353  Total_CL, Total_CD, Total_CSF, Total_CMx, Total_CMy, Total_CMz, Total_CFx, Total_CFy,
5354  Total_CFz, Total_CEff, Total_AoA, Total_Custom_ObjFunc);
5355  if (transp) SPRINTF(transp_coeff, ", %14.8e", Total_Cmu);
5356  if (buffet) SPRINTF (buffet_coeff, ", %14.8e", Total_Buffet_Metric);
5357  if (thermal || heat) SPRINTF (heat_coeff, ", %14.8e, %14.8e, %14.8e", Total_Heat, Total_MaxHeat, Total_Temperature);
5358  if (equiv_area) SPRINTF (equivalent_area_coeff, ", %14.8e, %14.8e", Total_CEquivArea, Total_CNearFieldOF);
5359  if (engine || actuator_disk) SPRINTF (engine_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", Total_NetThrust, Total_Power, Total_AeroCD, Total_SolidCD, Total_IDR, Total_IDC);
5360  if (rotating_frame) SPRINTF (rotating_frame_coeff, ", %14.8e, %14.8e, %14.8e", Total_CMerit, Total_CT, Total_CQ);
5361  if (inv_design) {
5362  SPRINTF (Cp_inverse_design, ", %14.8e", solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CpDiff());
5363  if (thermal && !turbo) SPRINTF (Heat_inverse_design, ", %14.8e", solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_HeatFluxDiff());
5364  }
5365 
5366  if (direct_diff != NO_DERIVATIVE) {
5367  if (!turbo)
5368  SPRINTF (d_direct_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e",
5369  D_Total_CL, D_Total_CD, D_Total_CSF, D_Total_CMx, D_Total_CMy, D_Total_CMz, D_Total_CFx, D_Total_CFy,
5370  D_Total_CFz, D_Total_CEff, D_Total_Custom_ObjFunc);
5371  else
5372  SPRINTF (d_direct_coeff, ", %12.10f, %12.10f, %12.10f, %12.10f, %12.10f", D_TotalPressure_Loss, D_FlowAngle_Out,
5373  D_TotalTotalEfficiency, D_TotalStaticEfficiency, D_EntropyGen);
5374  if (engine || actuator_disk)
5375  SPRINTF (d_direct_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e",
5376  D_Total_CL, D_Total_CD, D_Total_CSF, D_Total_CMx, D_Total_CMy, D_Total_CMz, D_Total_CFx, D_Total_CFy,
5377  D_Total_CFz, D_Total_CEff, D_Total_Custom_ObjFunc, D_Total_NetThrust, D_Total_Power, D_Total_AeroCD, D_Total_SolidCD, D_Total_IDR, D_Total_IDC);
5378  if (thermal)
5379  SPRINTF (d_direct_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e",
5380  D_Total_CL, D_Total_CD, D_Total_CSF, D_Total_CMx, D_Total_CMy, D_Total_CMz, D_Total_CFx, D_Total_CFy,
5381  D_Total_CFz, D_Total_CEff, D_Total_Custom_ObjFunc, D_Total_Heat, D_Total_MaxHeat);
5382  }
5383 
5384  if (aeroelastic) {
5385  for (iMarker_Monitoring = 0; iMarker_Monitoring < config[ZONE_0]->GetnMarker_Monitoring(); iMarker_Monitoring++) {
5386  //Append one by one the surface coeff to aeroelastic coeff. (Think better way do this, maybe use string)
5387  if (iMarker_Monitoring == 0) {
5388  SPRINTF(aeroelastic_coeff, ", %12.10f", aeroelastic_plunge[iMarker_Monitoring]);
5389  }
5390  else {
5391  SPRINTF(surface_coeff, ", %12.10f", aeroelastic_plunge[iMarker_Monitoring]);
5392  strcat(aeroelastic_coeff, surface_coeff);
5393  }
5394  SPRINTF(surface_coeff, ", %12.10f", aeroelastic_pitch[iMarker_Monitoring]);
5395  strcat(aeroelastic_coeff, surface_coeff);
5396  }
5397  }
5398 
5399  if (output_per_surface) {
5400  for (iMarker_Monitoring = 0; iMarker_Monitoring < config[ZONE_0]->GetnMarker_Monitoring(); iMarker_Monitoring++) {
5401  //Append one by one the surface coeff to monitoring coeff. (Think better way do this, maybe use string)
5402  if (iMarker_Monitoring == 0) {
5403  SPRINTF(monitoring_coeff, ", %12.10f", Surface_CL[iMarker_Monitoring]);
5404  }
5405  else {
5406  SPRINTF(surface_coeff, ", %12.10f", Surface_CL[iMarker_Monitoring]);
5407  strcat(monitoring_coeff, surface_coeff);
5408  }
5409  SPRINTF(surface_coeff, ", %12.10f", Surface_CD[iMarker_Monitoring]);
5410  strcat(monitoring_coeff, surface_coeff);
5411  SPRINTF(surface_coeff, ", %12.10f", Surface_CSF[iMarker_Monitoring]);
5412  strcat(monitoring_coeff, surface_coeff);
5413  SPRINTF(surface_coeff, ", %12.10f", Surface_CEff[iMarker_Monitoring]);
5414  strcat(monitoring_coeff, surface_coeff);
5415  SPRINTF(surface_coeff, ", %12.10f", Surface_CFx[iMarker_Monitoring]);
5416  strcat(monitoring_coeff, surface_coeff);
5417  SPRINTF(surface_coeff, ", %12.10f", Surface_CFy[iMarker_Monitoring]);
5418  strcat(monitoring_coeff, surface_coeff);
5419  SPRINTF(surface_coeff, ", %12.10f", Surface_CFz[iMarker_Monitoring]);
5420  strcat(monitoring_coeff, surface_coeff);
5421  SPRINTF(surface_coeff, ", %12.10f", Surface_CMx[iMarker_Monitoring]);
5422  strcat(monitoring_coeff, surface_coeff);
5423  SPRINTF(surface_coeff, ", %12.10f", Surface_CMy[iMarker_Monitoring]);
5424  strcat(monitoring_coeff, surface_coeff);
5425  SPRINTF(surface_coeff, ", %12.10f", Surface_CMz[iMarker_Monitoring]);
5426  strcat(monitoring_coeff, surface_coeff);
5427 
5428  if(buffet){
5429  SPRINTF(surface_coeff, ", %12.10f", Surface_Buffet_Metric[iMarker_Monitoring]);
5430  strcat(monitoring_coeff, surface_coeff);
5431  }
5432  }
5433  }
5434 
5435  if (turbo){
5436  for (iMarker_Monitoring = 0; iMarker_Monitoring < config[ZONE_0]->GetnMarker_TurboPerformance(); iMarker_Monitoring++){
5437  if (iMarker_Monitoring == 0){
5438  SPRINTF(turbo_coeff, ", %12.10f", TotalPressureLoss[iMarker_Monitoring][nSpanWiseSections]);
5439  }else{
5440  SPRINTF(surface_coeff, ", %12.10f", TotalPressureLoss[iMarker_Monitoring][nSpanWiseSections]);
5441  strcat(turbo_coeff, surface_coeff);
5442  }
5443  SPRINTF(surface_coeff, ", %12.10f", KineticEnergyLoss[iMarker_Monitoring][nSpanWiseSections]);
5444  strcat(turbo_coeff, surface_coeff);
5445  SPRINTF(surface_coeff, ", %12.10f", EntropyGen[iMarker_Monitoring][nSpanWiseSections]);
5446  strcat(turbo_coeff, surface_coeff);
5447  SPRINTF(surface_coeff, ", %12.10f", EulerianWork[iMarker_Monitoring][nSpanWiseSections]);
5448  strcat(turbo_coeff, surface_coeff);
5449  SPRINTF(surface_coeff, ", %12.10f", PressureRatio[iMarker_Monitoring][nSpanWiseSections]);
5450  strcat(turbo_coeff, surface_coeff);
5451  SPRINTF(surface_coeff, ", %12.10f", 180.0/PI_NUMBER*FlowAngleIn[iMarker_Monitoring][nSpanWiseSections]);
5452  strcat(turbo_coeff, surface_coeff);
5453  SPRINTF(surface_coeff, ", %12.10f", 180.0/PI_NUMBER*FlowAngleOut[iMarker_Monitoring][nSpanWiseSections]);
5454  strcat(turbo_coeff, surface_coeff);
5455  SPRINTF(surface_coeff, ", %12.10f", 180.0/PI_NUMBER*AbsFlowAngleIn[iMarker_Monitoring][nSpanWiseSections]);
5456  strcat(turbo_coeff, surface_coeff);
5457  SPRINTF(surface_coeff, ", %12.10f", 180.0/PI_NUMBER*AbsFlowAngleOut[iMarker_Monitoring][nSpanWiseSections]);
5458  strcat(turbo_coeff, surface_coeff);
5459  SPRINTF(surface_coeff, ", %12.10f", MassFlowIn[iMarker_Monitoring][nSpanWiseSections]);
5460  strcat(turbo_coeff, surface_coeff);
5461  SPRINTF(surface_coeff, ", %12.10f", MassFlowOut[iMarker_Monitoring][nSpanWiseSections]);
5462  strcat(turbo_coeff, surface_coeff);
5463  SPRINTF(surface_coeff, ", %12.10f", sqrt(MachIn[iMarker_Monitoring][nSpanWiseSections][1]*MachIn[iMarker_Monitoring][nSpanWiseSections][1] + MachIn[iMarker_Monitoring][nSpanWiseSections][0]*MachIn[iMarker_Monitoring][nSpanWiseSections][0]));
5464  strcat(turbo_coeff, surface_coeff);
5465  SPRINTF(surface_coeff, ", %12.10f", sqrt(MachOut[iMarker_Monitoring][nSpanWiseSections][1]*MachOut[iMarker_Monitoring][nSpanWiseSections][1] + MachOut[iMarker_Monitoring][nSpanWiseSections][0]*MachOut[iMarker_Monitoring][nSpanWiseSections][0]));
5466  strcat(turbo_coeff, surface_coeff);
5467  //
5468  SPRINTF(surface_coeff, ", %12.10f", TotalTotalEfficiency[iMarker_Monitoring][nSpanWiseSections]);
5469  strcat(turbo_coeff, surface_coeff);
5470  SPRINTF(surface_coeff, ", %12.10f", TotalStaticEfficiency[iMarker_Monitoring][nSpanWiseSections]);
5471  strcat(turbo_coeff, surface_coeff);
5472 
5473  }
5474  }
5475 
5476 
5477  /*--- Flow residual ---*/
5478  if (nDim == 2) {
5479  if (compressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), dummy);
5480  if (incompressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), dummy);
5481  }
5482  else {
5483  if (compressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), log10 (residual_flow[4]) );
5484  if (incompressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), log10 (residual_flow[4]));
5485  }
5486 
5487  /*--- Turbulent residual ---*/
5488  if (turbulent) {
5489  switch(nVar_Turb) {
5490  case 1: SPRINTF (turb_resid, ", %12.10f", log10 (residual_turbulent[0])); break;
5491  case 2: SPRINTF (turb_resid, ", %12.10f, %12.10f", log10(residual_turbulent[0]), log10(residual_turbulent[1])); break;
5492  }
5493  }
5494 
5495  /*---- Averaged stagnation pressure at an exit ----*/
5496 
5497  if (output_surface) {
5498  SPRINTF( surface_outputs, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", Surface_MassFlow, Surface_Mach, Surface_Temperature, Surface_Pressure, Surface_Density, Surface_Enthalpy, Surface_NormalVelocity, Surface_Uniformity, Surface_SecondaryStrength, Surface_MomentumDistortion, Surface_SecondOverUniform, Surface_TotalTemperature, Surface_TotalPressure, Surface_PressureDrop);
5499 
5500  if (direct_diff != NO_DERIVATIVE) {
5501  SPRINTF( d_surface_outputs, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e",
5502  D_Surface_Uniformity, D_Surface_SecondaryStrength, D_Surface_MomentumDistortion, D_Surface_SecondOverUniform, D_Surface_PressureDrop);
5503  }
5504  }
5505 
5506  /*--- Transition residual ---*/
5507  if (transition) {
5508  SPRINTF (trans_resid, ", %12.10f, %12.10f", log10(residual_transition[0]), log10(residual_transition[1]));
5509  }
5510 
5511  /*--- Combo objective ---*/
5512  if (output_comboObj) {
5513  SPRINTF(combo_obj,", %12.10f", Total_ComboObj);
5514  }
5515 
5516  /*--- Fluid structure residual ---*/
5517  // if (fluid_structure) {
5518  // if (nDim == 2) SPRINTF (levelset_resid, ", %12.10f, %12.10f, 0.0", log10 (residual_fea[0]), log10 (residual_fea[1]));
5519  // else SPRINTF (levelset_resid, ", %12.10f, %12.10f, %12.10f", log10 (residual_fea[0]), log10 (residual_fea[1]), log10 (residual_fea[2]));
5520  // }
5521 
5522  if (adjoint) {
5523 
5524  /*--- Adjoint coefficients ---*/
5525  if (!turbo) {
5526  if (compressible) {
5527  SPRINTF (adjoint_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, 0.0", Total_Sens_Geo, Total_Sens_Mach, Total_Sens_AoA, Total_Sens_Press, Total_Sens_Temp);
5528  }
5529  if (incompressible) {
5530  SPRINTF (adjoint_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e", Total_Sens_Geo, Total_Sens_ModVel, Total_Sens_BPressure, Total_Sens_Temp);
5531  }
5532  } else
5533  SPRINTF (adjoint_coeff, ", %14.8e, %14.8e, %14.8e", Total_Sens_Geo, Total_Sens_BPressure, Total_Sens_Temp);
5534 
5535  /*--- Adjoint flow residuals ---*/
5536  if (nDim == 2) {
5537  if (compressible) SPRINTF (adj_flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, 0.0", log10 (residual_adjflow[0]), log10 (residual_adjflow[1]), log10 (residual_adjflow[2]), log10 (residual_adjflow[3]) );
5538  if (incompressible) SPRINTF (adj_flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, 0.0", log10 (residual_adjflow[0]), log10 (residual_adjflow[1]), log10 (residual_adjflow[2]), log10 (residual_adjflow[3]) );
5539  }
5540  else {
5541  if (compressible) SPRINTF (adj_flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_adjflow[0]), log10 (residual_adjflow[1]), log10 (residual_adjflow[2]), log10 (residual_adjflow[3]), log10 (residual_adjflow[4]) );
5542  if (incompressible) SPRINTF (adj_flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_adjflow[0]), log10 (residual_adjflow[1]), log10 (residual_adjflow[2]), log10 (residual_adjflow[3]), log10 (residual_adjflow[4]));
5543  }
5544 
5545  /*--- Adjoint turbulent residuals ---*/
5546  if (turbulent)
5547  if (!frozen_visc) {
5548  if (nVar_AdjTurb == 1) {
5549  SPRINTF (adj_turb_resid, ", %14.8e", log10 (residual_adjturbulent[0]));
5550  } else if (nVar_AdjTurb > 1) {
5551  SPRINTF (adj_turb_resid, ", %14.8e, %14.8e", log10 (residual_adjturbulent[0]), log10 (residual_adjturbulent[1]));
5552  }
5553  }
5554 
5555  }
5556 
5557  if (weakly_coupled_heat) {
5558  SPRINTF (heat_resid, ", %14.8e", log10 (residual_heat[0]));
5559  }
5560 
5561  break;
5562 
5563  case HEAT_EQUATION_FVM:
5564 
5565  SPRINTF (direct_coeff, ", %14.8e, %14.8e, %14.8e", Total_Heat, Total_MaxHeat, Total_Temperature);
5566  SPRINTF (heat_resid, ", %14.8e", log10 (residual_heat[0]));
5567 
5568  break;
5569 
5570  case FEM_ELASTICITY:
5571 
5572  SPRINTF (begin_fem, ", %14.8e", 0.0);
5573 
5574  if (incload) SPRINTF (fem_coeff, ", %14.8e, %14.8e, %14.8e", Total_VMStress, Total_ForceCoeff, Total_IncLoad);
5575  else SPRINTF (fem_coeff, ", %14.8e, %14.8e", Total_VMStress, Total_ForceCoeff);
5576  /*--- FEM residual ---*/
5577  if (nDim == 2) {
5578  if (linear_analysis) SPRINTF (fem_resid, ", %14.8e, %14.8e, %14.8e", log10 (residual_fem[0]), log10 (residual_fem[1]), dummy);
5579  if (nonlinear_analysis) SPRINTF (fem_resid, ", %14.8e, %14.8e, %14.8e", log10 (residual_fem[0]), log10 (residual_fem[1]), log10 (residual_fem[2]));
5580  }
5581  else {
5582  SPRINTF (fem_resid, ", %14.8e, %14.8e, %14.8e", log10 (residual_fem[0]), log10 (residual_fem[1]), log10 (residual_fem[2]));
5583  }
5584  SPRINTF (end_fem, ", %lu, %12.10f\n", LinSolvIter, timeused/60.0);
5585 
5586  break;
5587 
5588  case DISC_ADJ_FEM:
5589 
5590  SPRINTF (direct_coeff, ", %12.10f", Total_VMStress);
5591  if (nDim == 2) {
5592  SPRINTF (fem_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_fem[0]), log10 (residual_fem[1]), dummy, dummy, dummy);
5593  }
5594  else {
5595  SPRINTF (fem_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_fem[0]), log10 (residual_fem[1]), log10 (residual_fem[2]), dummy, dummy);
5596  }
5597 
5598  break;
5599 
5600  }
5601  }
5602  if ((val_iZone == 0 && val_iInst == 0)|| fluid_structure){
5603  /*--- Write the screen header---*/
5604  if ( (!fem && ((write_heads) && !(!DualTime_Iteration && Unsteady))) ||
5605  (fem && ((write_heads_FEM) && !(!DualTime_Iteration && nonlinear_analysis)))
5606  ) {
5607 
5608  if (!fem) {
5609  if (!Unsteady && (config[val_iZone]->GetUnsteady_Simulation() != TIME_STEPPING)) {
5610  switch (config[val_iZone]->GetKind_Solver()) {
5611  case EULER : case NAVIER_STOKES: case RANS:
5612  case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES:
5613  case ADJ_EULER : case ADJ_NAVIER_STOKES: case ADJ_RANS:
5614 
5615  cout << endl << "---------------------- Local Time Stepping Summary ----------------------" << endl;
5616 
5617  for (unsigned short iMesh = FinestMesh; iMesh <= config[val_iZone]->GetnMGLevels(); iMesh++)
5618  cout << "MG level: "<< iMesh << " -> Min. DT: " << solver_container[val_iZone][val_iInst][iMesh][FLOW_SOL]->GetMin_Delta_Time()<<
5619  ". Max. DT: " << solver_container[val_iZone][val_iInst][iMesh][FLOW_SOL]->GetMax_Delta_Time() <<
5620  ". CFL: " << config[val_iZone]->GetCFL(iMesh) << "." << endl;
5621 
5622  if (nZone > 1)
5623  cout << "CFL in zone 2: " << config[1]->GetCFL(MESH_0) << endl;
5624 
5625  cout << "-------------------------------------------------------------------------" << endl;
5626 
5627  if (direct_diff != NO_DERIVATIVE) {
5628  cout << endl << "---------------------- Direct Differentiation Summary -------------------" << endl;
5629  cout << "Coefficients are differentiated with respect to ";
5630  switch (direct_diff) {
5631  case D_MACH:
5632  cout << "Mach number." << endl;
5633  break;
5634  case D_AOA:
5635  cout << "AoA." << endl;
5636  break;
5637  case D_SIDESLIP:
5638  cout << "AoS." << endl;
5639  break;
5640  case D_REYNOLDS:
5641  cout << "Reynolds number." << endl;
5642  break;
5643  case D_TURB2LAM:
5644  cout << "Turb/Lam ratio." << endl;
5645  break;
5646  case D_PRESSURE:
5647  cout << "Freestream Pressure." << endl;
5648  break;
5649  case D_TEMPERATURE:
5650  cout << "Freestream Temperature." << endl;
5651  break;
5652  case D_DENSITY:
5653  cout << "Freestream Density." << endl;
5654  break;
5655  case D_VISCOSITY:
5656  cout << "Freestream Viscosity." << endl;
5657  break;
5658  case D_DESIGN:
5659  cout << "Design Variables." << endl;
5660  break;
5661  default:
5662  break;
5663  }
5664 
5665  cout << " D_CLift(Total)" << " D_CDrag(Total)" << " D_CMz(Total)" <<" D_CEff(Total)" << endl;
5666  cout.width(18); cout << D_Total_CL;
5667  cout.width(18); cout << D_Total_CD;
5668  cout.width(18); cout << D_Total_CMz;
5669  cout.width(18); cout << D_Total_CEff;
5670  cout << endl << "-------------------------------------------------------------------------" << endl;
5671  cout << endl;
5672  }
5673  if (turbo && write_turbo && val_iZone== 0){
5674  WriteTurboPerfConvHistory(config[val_iZone]);
5675  }
5676  break;
5677 
5679  cout << endl;
5680  cout << "------------------------ Discrete Adjoint Summary -----------------------" << endl;
5681  cout << "Total Geometry Sensitivity (updated every " << config[val_iZone]->GetWrt_Sol_Freq() << " iterations): ";
5682  cout.precision(4);
5683  cout.setf(ios::scientific, ios::floatfield);
5684  cout << Total_Sens_Geo;
5685  cout << endl << "-------------------------------------------------------------------------" << endl;
5686  break;
5687 
5688  }
5689  }
5690  else {
5691  if (flow) {
5692  if ((config[val_iZone]->GetUnsteady_Simulation() == TIME_STEPPING) && (config[val_iZone]->GetUnst_CFL()== 0.0))
5693  {
5694  cout << endl << "Min DT: " << solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetMin_Delta_Time()<< ".Max DT: " << solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetMax_Delta_Time() << ".Time step: " << config[val_iZone]->GetDelta_UnstTimeND() << ".";
5695  } else if ((config[val_iZone]->GetUnsteady_Simulation() == TIME_STEPPING) && (config[val_iZone]->GetUnst_CFL()!= 0.0)) {
5696  cout << endl << "Min DT: " << solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetMin_Delta_Time()<< ".Max DT: " << solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetMax_Delta_Time() << ". Time step: " << solver_container[val_iZone][val_iInst][config[val_iZone]->GetFinestMesh()][FLOW_SOL]->GetMin_Delta_Time() << ". CFL: " << config[val_iZone]->GetUnst_CFL()<<".";
5697  } else {
5698  cout << endl << "Min DT: " << solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetMin_Delta_Time()<< ".Max DT: " << solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetMax_Delta_Time() << ".Dual Time step: " << config[val_iZone]->GetDelta_UnstTimeND() << ".";
5699  }
5700  } else {
5701  cout << endl << "Dual Time step: " << config[val_iZone]->GetDelta_UnstTimeND() << ".";
5702  }
5703  }
5704  }
5705  else if (fem && !fsi) {
5706  if (dynamic) {
5707  cout << endl << "Simulation time: " << config[val_iZone]->GetCurrent_DynTime() << ". Time step: " << config[val_iZone]->GetDelta_DynTime() << ".";
5708  }
5709  }
5710 
5711  switch (config[val_iZone]->GetKind_Solver()) {
5712  case EULER : case NAVIER_STOKES:
5713  case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_LES:
5714 
5715  /*--- Visualize the maximum residual ---*/
5716  iPointMaxResid = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetPoint_Max(0);
5717  Coord = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetPoint_Max_Coord(0);
5718 
5719  cout << endl << "----------------------- Residual Evolution Summary ----------------------" << endl;
5720 
5721  cout << "log10[Maximum residual]: " << log10(solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetRes_Max(0)) << "." << endl;
5722 
5723  if (config[val_iZone]->GetSystemMeasurements() == SI) {
5724  cout <<"Maximum residual point " << iPointMaxResid << ", located at (" << Coord[0] << ", " << Coord[1];
5725  if (nDim == 3) cout << ", " << Coord[2];
5726  cout << ")." << endl;
5727  }
5728  else {
5729  cout <<"Maximum residual point " << iPointMaxResid << ", located at (" << Coord[0]*12.0 << ", " << Coord[1]*12.0;
5730  if (nDim == 3) cout << ", " << Coord[2]*12.0;
5731  cout << ")." << endl;
5732  }
5733 
5734  /*--- Print out the number of non-physical points and reconstructions ---*/
5735 
5736  if (config[val_iZone]->GetNonphysical_Points() > 0)
5737  cout << "There are " << config[val_iZone]->GetNonphysical_Points() << " non-physical points in the solution." << endl;
5738  if (config[val_iZone]->GetNonphysical_Reconstr() > 0)
5739  cout << "There are " << config[val_iZone]->GetNonphysical_Reconstr() << " non-physical states in the upwind reconstruction." << endl;
5740 
5741  cout << "-------------------------------------------------------------------------" << endl;
5742 
5743  if (!Unsteady) cout << endl << " Iter" << " Time(s)";
5744  else cout << endl << " IntIter" << " ExtIter";
5745 
5746  // if (!fluid_structure) {
5747  if (incompressible && !weakly_coupled_heat) {
5748  if (energy) {cout << " Res[Press]" << " Res[Temp]" << " CLift(Total)" << " CDrag(Total)" << endl;}
5749  else {cout << " Res[Press]" << " Res[Velx]" << " CLift(Total)" << " CDrag(Total)" << endl;}
5750  }
5751  else if (incompressible && weakly_coupled_heat) cout << " Res[Press]" << " Res[Heat]" << " HFlux(Total)";
5752  else if (rotating_frame && nDim == 3 && !turbo) cout << " Res[Rho]" << " Res[RhoE]" << " CThrust(Total)" << " CTorque(Total)" << endl;
5753  else if (aeroelastic) cout << " Res[Rho]" << " Res[RhoE]" << " CLift(Total)" << " CDrag(Total)" << " plunge" << " pitch" << endl;
5754  else if (equiv_area) cout << " Res[Rho]" << " CLift(Total)" << " CDrag(Total)" << " CPress(N-F)" << endl;
5755 
5756  else if (turbo){
5757 
5758  if(nZone < 2){
5759  /*--- single zone output ---*/
5760  cout << " Res[Rho]" << " Res[RhoE]" << " TotPresLoss(%)" << " Entropy Gen.(%)";
5761  }
5762  else{
5763  /* --- multi-zone output ---*/
5764  cout << " Res[Rho]" << " Res[RhoE]" << " TTEfficiency(%)" << " Entropy Gen.(%)";
5765  }
5766  }
5767 
5768  else if (actuator_disk) cout << " Res[Rho]" << " Res[RhoE]" << " CL(Total)" << " CD-CT(Total)";
5769  else if (engine) cout << " Res[Rho]" << " Res[RhoE]" << " CL(Total)" << " CD-CT(Total)";
5770  else cout << " Res[Rho]" << " Res[RhoE]" << " CL(Total)" << " CD(Total)";
5771 
5772  if(extra_heat_output) {
5773  cout << " Res[Heat]" << " HFlux(Total)";
5774  }
5775 
5776  cout << endl;
5777 
5778  break;
5779 
5780  case RANS :
5781 
5782  /*--- Visualize the maximum residual ---*/
5783  iPointMaxResid = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetPoint_Max(0);
5784  Coord = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetPoint_Max_Coord(0);
5785 
5786  cout << endl << "----------------------- Residual Evolution Summary ----------------------" << endl;
5787 
5788  cout << "log10[Maximum residual]: " << log10(solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetRes_Max(0)) << "." << endl;
5789  if (config[val_iZone]->GetSystemMeasurements() == SI) {
5790  cout <<"Maximum residual point " << iPointMaxResid << ", located at (" << Coord[0] << ", " << Coord[1];
5791  if (nDim == 3) cout << ", " << Coord[2];
5792  cout << ")." << endl;
5793  }
5794  else {
5795  cout <<"Maximum residual point " << iPointMaxResid << ", located at (" << Coord[0]*12.0 << ", " << Coord[1]*12.0;
5796  if (nDim == 3) cout << ", " << Coord[2]*12.0;
5797  cout << ")." << endl;
5798  }
5799  cout <<"Maximum Omega " << solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetOmega_Max() << ", maximum Strain Rate " << solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetStrainMag_Max() << "." << endl;
5800 
5801  /*--- Print out the number of non-physical points and reconstructions ---*/
5802  if (config[val_iZone]->GetNonphysical_Points() > 0)
5803  cout << "There are " << config[val_iZone]->GetNonphysical_Points() << " non-physical points in the solution." << endl;
5804  if (config[val_iZone]->GetNonphysical_Reconstr() > 0)
5805  cout << "There are " << config[val_iZone]->GetNonphysical_Reconstr() << " non-physical states in the upwind reconstruction." << endl;
5806 
5807  cout << "-------------------------------------------------------------------------" << endl;
5808 
5809  if (!Unsteady) cout << endl << " Iter" << " Time(s)";
5810  else cout << endl << " IntIter" << " ExtIter";
5811  if (incompressible) cout << " Res[Press]";
5812  else cout << " Res[Rho]";//, cout << " Res[RhoE]";
5813 
5814  switch (config[val_iZone]->GetKind_Turb_Model()) {
5815  case SA: case SA_NEG: case SA_E: case SA_E_COMP: case SA_COMP: cout << " Res[nu]"; break;
5816  case SST: cout << " Res[kine]" << " Res[omega]"; break;
5817  }
5818 
5819  if (weakly_coupled_heat) {
5820  cout << " Res[Heat]";
5821  }
5822 
5823  if (transition) { cout << " Res[Int]" << " Res[Re]"; }
5824  else if (rotating_frame && nDim == 3 && !turbo ) cout << " CThrust(Total)" << " CTorque(Total)";
5825  else if (aeroelastic) cout << " CLift(Total)" << " CDrag(Total)" << " plunge" << " pitch";
5826  else if (equiv_area) cout << " CLift(Total)" << " CDrag(Total)" << " CPress(N-F)";
5827  else if (turbo){
5828  if (nZone < 2){
5829  /*--- single zone output ---*/
5830  cout << " TotPresLoss(%)" << " Entropy Gen.(%)";
5831  }
5832  else{
5833  /*--- multi zone output ---*/
5834  cout << " TTEfficiency(%)" << " Entropy Gen.(%)";
5835 
5836  }
5837  }
5838  else if (weakly_coupled_heat) {
5839  cout << " HFlux(Total)";
5840  }
5841  else cout << " CLift(Total)" << " CDrag(Total)";
5842 
5843  if(extra_heat_output) {
5844  cout << " Res[Heat]" << " HFlux(Total)";
5845  }
5846 
5847  cout << endl;
5848 
5849  break;
5850 
5851  case HEAT_EQUATION_FVM :
5852  if (!Unsteady) cout << endl << " Iter" << " Time(s)";
5853  else cout << endl << " IntIter" << " ExtIter";
5854 
5855  cout << " Res[Heat]" << " HFlux(Total)";
5856  break;
5857 
5858  case FEM_ELASTICITY :
5859  if (!nonlinear_analysis) cout << endl << " Iter" << " Time(s)";
5860  else cout << endl << " IntIter" << " ExtIter";
5861 
5862  if (linear_analysis) {
5863  if (nDim == 2) cout << " Res[Displx]" << " Res[Disply]" << " VMS(Max)"<< endl;
5864  if (nDim == 3) cout << " Res[Displx]" << " Res[Disply]" << " Res[Displz]" << " VMS(Max)"<< endl;
5865  }
5866  else if (nonlinear_analysis) {
5867  switch (config[val_iZone]->GetResidual_Criteria_FEM()) {
5868  case RESFEM_RELATIVE:
5869  cout << " Res[UTOL]" << " Res[RTOL]" << " Res[ETOL]" << " VMS(Max)"<< endl;
5870  break;
5871  case RESFEM_ABSOLUTE:
5872  cout << " Res[UTOL-A]" << " Res[RTOL-A]" << " Res[ETOL-A]" << " VMS(Max)"<< endl;
5873  break;
5874  default:
5875  cout << " Res[UTOL]" << " Res[RTOL]" << " Res[ETOL]" << " VMS(Max)"<< endl;
5876  break;
5877  }
5878  }
5879  break;
5880 
5881  case ADJ_EULER : case ADJ_NAVIER_STOKES :
5883 
5884  /*--- Visualize the maximum residual ---*/
5885  iPointMaxResid = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetPoint_Max(0);
5886  Coord = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetPoint_Max_Coord(0);
5887  cout << endl << "log10[Maximum residual]: " << log10(solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetRes_Max(0)) << "." << endl;
5888  if (config[val_iZone]->GetSystemMeasurements() == SI) {
5889  cout <<"Maximum residual point " << iPointMaxResid << ", located at (" << Coord[0] << ", " << Coord[1];
5890  if (nDim == 3) cout << ", " << Coord[2];
5891  cout << ")." << endl;
5892  }
5893  else {
5894  cout <<"Maximum residual point " << iPointMaxResid << ", located at (" << Coord[0]*12.0 << ", " << Coord[1]*12.0;
5895  if (nDim == 3) cout << ", " << Coord[2]*12.0;
5896  cout << ")." << endl;
5897  }
5898 
5899  /*--- Print out the number of non-physical points and reconstructions ---*/
5900  if (config[val_iZone]->GetNonphysical_Points() > 0)
5901  cout << "There are " << config[val_iZone]->GetNonphysical_Points() << " non-physical points in the solution." << endl;
5902 
5903  if (!Unsteady) cout << endl << " Iter" << " Time(s)";
5904  else cout << endl << " IntIter" << " ExtIter";
5905 
5906  if (incompressible) {
5907  if (energy) {cout << " Res[Psi_Press]" << " Res[Psi_Temp]";}
5908  else {cout << " Res[Psi_Press]" << " Res[Psi_Velx]";}
5909  }
5910  else cout << " Res[Psi_Rho]" << " Res[Psi_E]";
5911  if (disc_adj) {
5912  if (!turbo){
5913  if (compressible) {
5914  cout << " Sens_Press" << " Sens_AoA" << endl;
5915  }
5916  if (incompressible) {
5917  if (energy) {
5918  cout << " Sens_Vin" << " Sens_Temp" << endl;
5919  } else {
5920  cout << " Sens_Vin" << " Sens_Pout" << endl;
5921  }
5922  } } else {
5923  cout << " Sens_PressOut" << " Sens_TotTempIn" << endl;
5924  }
5925  } else {
5926  cout << " Sens_Geo" << " Sens_AoA" << endl;
5927  }
5928  break;
5929 
5930  case ADJ_RANS : case DISC_ADJ_RANS:
5931 
5932  /*--- Visualize the maximum residual ---*/
5933  iPointMaxResid = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetPoint_Max(0);
5934  Coord = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetPoint_Max_Coord(0);
5935  cout << endl << "log10[Maximum residual]: " << log10(solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetRes_Max(0)) << "." << endl;
5936  if (config[val_iZone]->GetSystemMeasurements() == SI) {
5937  cout <<"Maximum residual point " << iPointMaxResid << ", located at (" << Coord[0] << ", " << Coord[1];
5938  if (nDim == 3) cout << ", " << Coord[2];
5939  cout << ")." << endl;
5940  }
5941  else {
5942  cout <<"Maximum residual point " << iPointMaxResid << ", located at (" << Coord[0]*12.0 << ", " << Coord[1]*12.0;
5943  if (nDim == 3) cout << ", " << Coord[2]*12.0;
5944  cout << ")." << endl;
5945  }
5946 
5947  /*--- Print out the number of non-physical points and reconstructions ---*/
5948  if (config[val_iZone]->GetNonphysical_Points() > 0)
5949  cout << "There are " << config[val_iZone]->GetNonphysical_Points() << " non-physical points in the solution." << endl;
5950 
5951  if (!Unsteady) cout << endl << " Iter" << " Time(s)";
5952  else cout << endl << " IntIter" << " ExtIter";
5953 
5954  if (incompressible) cout << " Res[Psi_Press]";
5955  else cout << " Res[Psi_Rho]";
5956 
5957  if (!frozen_visc) {
5958  cout << " Res[Psi_Turb[0]]";
5959  }
5960  else {
5961  if (incompressible) {if (energy) {cout << " Res[Psi_Temp]";}
5962  else {cout << " Res[Psi_Velx]";}}
5963  else cout << " Res[Psi_E]";
5964  }
5965  if (disc_adj) {
5966  if (!turbo){
5967  if (compressible) {
5968  cout << " Sens_Press" << " Sens_AoA" << endl;
5969  }
5970  if (incompressible) {
5971  cout << " Sens_Vin" << " Sens_Pout" << endl;
5972  }
5973  } else {
5974  cout << " Sens_PressOut" << " Sens_TotTempIn" << endl; }
5975  } else {
5976  cout << " Sens_Geo" << " Sens_AoA" << endl;
5977  }
5978  break;
5979 
5980  case DISC_ADJ_FEM :
5981  cout << endl << " IntIter" << " ExtIter";
5982 
5983  if (nDim == 2) cout << " Res[Ux_adj]" << " Res[Uy_adj]" << " Sens[E]" << " Sens[Nu]"<< endl;
5984  if (nDim == 3) cout << " Res[Ux_adj]" << " Res[Uy_adj]" << " Res[Uz_adj]" << " Sens[E]" << " Sens[Nu]"<< endl;
5985 
5986  break;
5987 
5988  }
5989 
5990  }
5991  }
5992 
5993  /*--- Write the solution on the screen ---*/
5994 
5995  if ((val_iZone == 0 && val_iInst == 0)|| fluid_structure){
5996  cout.precision(6);
5997  cout.setf(ios::fixed, ios::floatfield);
5998  if (!fem) {
5999  if (!Unsteady) {
6000  cout.width(5); cout << iExtIter + ExtIter_OffSet;
6001  cout.width(11); cout << timeiter;
6002 
6003  } else if (Unsteady && DualTime_Iteration) {
6004  cout.width(8); cout << iIntIter;
6005  cout.width(8); cout << iExtIter;
6006  }
6007  }
6008  else if (fem) {
6009  if (!DualTime_Iteration) {
6010  if (!nonlinear_analysis) {
6011  cout.width(5); cout << iExtIter;
6012  cout.width(11); cout << timeiter;
6013 
6014  } else {
6015  cout.width(8); cout << iIntIter;
6016  cout.width(8); cout << iExtIter;
6017  }
6018  }
6019  else if (discadj_fem){
6020  cout.width(8); cout << iIntIter;
6021  cout.width(8); cout << iExtIter;
6022  }
6023  }
6024  }
6025 
6026  switch (config[val_iZone]->GetKind_Solver()) {
6027  case EULER : case NAVIER_STOKES:
6028  case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_LES:
6029 
6030  /*--- Write history file ---*/
6031 
6032  if ((!DualTime_Iteration) && (output_files)) {
6033  if (!turbo) {
6034  ConvHist_file[0] << begin << direct_coeff;
6035  if (transp) ConvHist_file[0] << transp_coeff;
6036  if (buffet) ConvHist_file[0] << buffet_coeff;
6037  if (thermal) ConvHist_file[0] << heat_coeff;
6038  if (equiv_area) ConvHist_file[0] << equivalent_area_coeff;
6039  if (engine || actuator_disk) ConvHist_file[0] << engine_coeff;
6040  if (inv_design) {
6041  ConvHist_file[0] << Cp_inverse_design;
6042  if (thermal) ConvHist_file[0] << Heat_inverse_design;
6043  }
6044  if (rotating_frame && !turbo) ConvHist_file[0] << rotating_frame_coeff;
6045  ConvHist_file[0] << flow_resid;
6046  if (weakly_coupled_heat) ConvHist_file[0] << heat_resid;
6047  }
6048  else {
6049  ConvHist_file[0] << begin << turbo_coeff << flow_resid;
6050  }
6051 
6052  if (aeroelastic) ConvHist_file[0] << aeroelastic_coeff;
6053  if (output_per_surface) ConvHist_file[0] << monitoring_coeff;
6054  if (output_surface) ConvHist_file[0] << surface_outputs;
6055  if (direct_diff != NO_DERIVATIVE) {
6056  ConvHist_file[0] << d_direct_coeff;
6057  if (output_surface) ConvHist_file[0] << d_surface_outputs;
6058  }
6059  if (output_comboObj) ConvHist_file[0] << combo_obj;
6060  ConvHist_file[0] << end;
6061  ConvHist_file[0].flush();
6062  }
6063 
6064  /*--- Write screen output ---*/
6065  if ((val_iZone == 0 && val_iInst == 0)|| fluid_structure){
6066  if(DualTime_Iteration || !Unsteady) {
6067  cout.precision(6);
6068  cout.setf(ios::fixed, ios::floatfield);
6069  cout.width(13); cout << log10(residual_flow[0]);
6070  if (!equiv_area) {
6071  if (compressible) {
6072  if (nDim == 2 ) { cout.width(14); cout << log10(residual_flow[3]); }
6073  else { cout.width(14); cout << log10(residual_flow[4]); }
6074  }
6075  if (incompressible && !weakly_coupled_heat) {
6076  if (energy) {cout.width(14); cout << log10(residual_flow[nDim+1]);}
6077  else {cout.width(14); cout << log10(residual_flow[1]);}
6078  }
6079  if (incompressible && weakly_coupled_heat) { cout.width(14); cout << log10(residual_heat[0]);}
6080 
6081  }
6082 
6083  if (rotating_frame && nDim == 3 && !turbo ) {
6084  cout.setf(ios::scientific, ios::floatfield);
6085  cout.width(15); cout << Total_CT;
6086  cout.width(15); cout << Total_CQ;
6087  cout.unsetf(ios_base::floatfield);
6088  }
6089  else if (equiv_area) { cout.width(15); cout << min(10000.0, max(-10000.0, Total_CL)); cout.width(15); cout << min(10000.0, max(-10000.0, Total_CD)); cout.width(15);
6090  cout.precision(4);
6091  cout.setf(ios::scientific, ios::floatfield);
6092  cout << Total_CNearFieldOF; }
6093  else if (turbo) {
6094  cout.setf(ios::scientific, ios::floatfield);
6095 
6096  if (nZone < 2) {
6097  cout.width(15); cout << TotalPressureLoss[0][nSpanWiseSections]*100.0;
6098  cout.width(15); cout << EntropyGen[0][nSpanWiseSections]*100.0;
6099  }
6100  else {
6101  cout.width(15); cout << TotalTotalEfficiency[nTurboPerf -1][nSpanWiseSections]*100.0;
6102  cout.width(15); cout << EntropyGen[nTurboPerf -1][nSpanWiseSections]*100.0;
6103  }
6104 
6105  cout.unsetf(ios_base::floatfield);
6106 
6107  }
6108  else if (weakly_coupled_heat) { cout.width(14); cout << log10(Total_Heat); }
6109  else { cout.width(15); cout << min(10000.0, max(-10000.0, Total_CL)); cout.width(15); cout << min(10000.0, max(-10000.0, Total_CD)); }
6110  if (aeroelastic) {
6111  cout.setf(ios::scientific, ios::floatfield);
6112  cout.width(15); cout << aeroelastic_plunge[0]; //Only output the first marker being monitored to the console.
6113  cout.width(15); cout << aeroelastic_pitch[0];
6114  cout.unsetf(ios_base::floatfield);
6115  }
6116 
6117  if (extra_heat_output) { cout.width(15); cout << Extra_Heat_Residual; cout.width(15); cout << Extra_Total_Heat; }
6118  }
6119  cout << endl;
6120  }
6121  break;
6122 
6123  case RANS :
6124 
6125  /*--- Write history file ---*/
6126 
6127  if ((!DualTime_Iteration) && (output_files)) {
6128 
6129  if (!turbo) {
6130  ConvHist_file[0] << begin << direct_coeff;
6131  if (transp) ConvHist_file[0] << transp_coeff;
6132  if (buffet) ConvHist_file[0] << buffet_coeff;
6133  if (thermal) ConvHist_file[0] << heat_coeff;
6134  if (equiv_area) ConvHist_file[0] << equivalent_area_coeff;
6135  if (engine || actuator_disk) ConvHist_file[0] << engine_coeff;
6136  if (inv_design) {
6137  ConvHist_file[0] << Cp_inverse_design;
6138  if (thermal) ConvHist_file[0] << Heat_inverse_design;
6139  }
6140  if (rotating_frame && !turbo) ConvHist_file[0] << rotating_frame_coeff;
6141  ConvHist_file[0] << flow_resid << turb_resid;
6142  if (weakly_coupled_heat) ConvHist_file[0] << heat_resid;
6143  }
6144  else {
6145  ConvHist_file[0] << begin << turbo_coeff << flow_resid << turb_resid;
6146  }
6147 
6148  if (aeroelastic) ConvHist_file[0] << aeroelastic_coeff;
6149  if (output_per_surface) ConvHist_file[0] << monitoring_coeff;
6150  if (output_surface) ConvHist_file[0] << surface_outputs;
6151  if (direct_diff != NO_DERIVATIVE) {
6152  ConvHist_file[0] << d_direct_coeff;
6153  if (output_surface) ConvHist_file[0] << d_surface_outputs;
6154  }
6155  if (output_comboObj) ConvHist_file[0] << combo_obj;
6156  ConvHist_file[0] << end;
6157  ConvHist_file[0].flush();
6158  }
6159 
6160  /*--- Write screen output ---*/
6161 
6162  if ((val_iZone == 0 && val_iInst == 0)|| fluid_structure){
6163  if(DualTime_Iteration || !Unsteady) {
6164  cout.precision(6);
6165  cout.setf(ios::fixed, ios::floatfield);
6166 
6167  if (incompressible) cout.width(13);
6168  else cout.width(14);
6169  cout << log10(residual_flow[0]);
6170  switch(nVar_Turb) {
6171  case 1: cout.width(14); cout << log10(residual_turbulent[0]); break;
6172  case 2: cout.width(14); cout << log10(residual_turbulent[0]);
6173  cout.width(15); cout << log10(residual_turbulent[1]); break;
6174  }
6175 
6176  if (weakly_coupled_heat) {
6177  cout.width(14); cout << log10(residual_heat[0]);
6178  }
6179 
6180  if (transition) { cout.width(14); cout << log10(residual_transition[0]); cout.width(14); cout << log10(residual_transition[1]); }
6181 
6182  if (rotating_frame && nDim == 3 && !turbo ) {
6183  cout.setf(ios::scientific, ios::floatfield);
6184  cout.width(15); cout << Total_CT; cout.width(15);
6185  cout << Total_CQ;
6186  cout.unsetf(ios_base::floatfield);
6187  }
6188  else if (equiv_area) { cout.width(15); cout << min(10000.0, max(-10000.0, Total_CL)); cout.width(15); cout << min(10000.0, max(-10000.0, Total_CD)); cout.width(15);
6189  cout.precision(4);
6190  cout.setf(ios::scientific, ios::floatfield);
6191  cout << Total_CNearFieldOF; }
6192  else if (turbo) {
6193  cout.setf(ios::scientific, ios::floatfield);
6194  if (nZone < 2){
6195  /*--- single zone output ---*/
6196  cout.width(15); cout << TotalPressureLoss[0][nSpanWiseSections]*100.0;
6197  cout.width(15); cout << EntropyGen[0][nSpanWiseSections]*100.0;
6198  }
6199  else{
6200  /*--- multi zone output ---*/
6201  cout.width(15); cout << TotalTotalEfficiency[nTurboPerf - 1][nSpanWiseSections]*100.0;
6202  cout.width(15); cout << EntropyGen[nTurboPerf -1][nSpanWiseSections]*100.0;
6203  if (direct_diff){
6204  cout.width(15); cout << D_EntropyGen;
6205  }
6206  }
6207  cout.unsetf(ios_base::floatfield);
6208  }
6209  else if (weakly_coupled_heat) { cout.width(15); cout << Total_Heat; }
6210  else { cout.width(15); cout << min(10000.0, max(-10000.0, Total_CL)); cout.width(15); cout << min(10000.0, max(-10000.0, Total_CD)); }
6211 
6212  if (aeroelastic) {
6213  cout.setf(ios::scientific, ios::floatfield);
6214  cout.width(15); cout << aeroelastic_plunge[0]; //Only output the first marker being monitored to the console.
6215  cout.width(15); cout << aeroelastic_pitch[0];
6216  cout.unsetf(ios_base::floatfield);
6217  }
6218 
6219  if (extra_heat_output) { cout.width(15); cout << Extra_Heat_Residual; cout.width(15); cout << Extra_Total_Heat; }
6220  cout << endl;
6221  }
6222  }
6223  break;
6224 
6225 
6226  case HEAT_EQUATION_FVM:
6227 
6228  if (!DualTime_Iteration) {
6229  ConvHist_file[0] << begin << direct_coeff << heat_resid << end;
6230  ConvHist_file[0].flush();
6231  }
6232  break;
6233 
6234  case FEM_ELASTICITY:
6235 
6236  if (!DualTime_Iteration) {
6237  config[val_iZone]->GetHistFile()[0] << begin << fem_coeff << fem_resid << end_fem;
6238  config[val_iZone]->GetHistFile()[0].flush();
6239 
6240  cout.precision(6);
6241  cout.setf(ios::fixed, ios::floatfield);
6242  if (linear_analysis) {
6243  cout.width(14); cout << log10(residual_fem[0]);
6244  cout.width(14); cout << log10(residual_fem[1]);
6245  if (nDim == 3) { cout.width(14); cout << log10(residual_fem[2]); }
6246  }
6247  else if (nonlinear_analysis) {
6248  cout.width(14); cout << log10(residual_fem[0]);
6249  cout.width(14); cout << log10(residual_fem[1]);
6250  cout.width(14); cout << log10(residual_fem[2]);
6251  }
6252 
6253  cout.precision(4);
6254  cout.setf(ios::scientific, ios::floatfield);
6255  cout.width(14); cout << Total_VMStress;
6256  cout << endl;
6257  }
6258  break;
6259 
6260  case DISC_ADJ_FEM:
6261 
6262  cout.precision(6);
6263  cout.setf(ios::fixed, ios::floatfield);
6264 
6265  cout.width(15); cout << log10(residual_fem[0]);
6266  cout.width(15); cout << log10(residual_fem[1]);
6267  if (nDim == 3) { cout.width(15); cout << log10(residual_fem[2]); }
6268 
6269  cout.precision(4);
6270  cout.setf(ios::scientific, ios::floatfield);
6271 
6272 
6273  if (config[val_iZone]->GetnElasticityMod() == 1){
6274  cout.width(14); cout << solver_container[val_iZone][val_iInst][FinestMesh][ADJFEA_SOL]->GetGlobal_Sens_E(0);
6275  cout.width(14); cout << solver_container[val_iZone][val_iInst][FinestMesh][ADJFEA_SOL]->GetGlobal_Sens_Nu(0);
6276  }
6277  else{
6278  Total_SensE = 0.0; Total_SensNu = 0.0;
6279  for (unsigned short iVar = 0; iVar < config[val_iZone]->GetnElasticityMod(); iVar++){
6280  Total_SensE += solver_container[val_iZone][val_iInst][FinestMesh][ADJFEA_SOL]->GetGlobal_Sens_E(0)
6281  *solver_container[val_iZone][val_iInst][FinestMesh][ADJFEA_SOL]->GetGlobal_Sens_E(0);
6282  Total_SensNu += solver_container[val_iZone][val_iInst][FinestMesh][ADJFEA_SOL]->GetGlobal_Sens_Nu(0)
6283  *solver_container[val_iZone][val_iInst][FinestMesh][ADJFEA_SOL]->GetGlobal_Sens_Nu(0);
6284  }
6285  Total_SensE = sqrt(Total_SensE);
6286  Total_SensNu = sqrt(Total_SensNu);
6287  cout.width(14); cout << Total_SensE;
6288  cout.width(14); cout << Total_SensNu;
6289  }
6290 
6291  cout << endl;
6292  break;
6293 
6294  case ADJ_EULER : case ADJ_NAVIER_STOKES :
6296 
6297  if (!DualTime_Iteration) {
6298  ConvHist_file[0] << begin << adjoint_coeff << adj_flow_resid << end;
6299  ConvHist_file[0].flush();
6300  }
6301  if ((val_iZone == 0 && val_iInst == 0)|| fluid_structure){
6302  if (DualTime_Iteration || !Unsteady){
6303  cout.precision(6);
6304  cout.setf(ios::fixed, ios::floatfield);
6305  if (compressible) {
6306  cout.width(15); cout << log10(residual_adjflow[0]);
6307  cout.width(15); cout << log10(residual_adjflow[nDim+1]);
6308  }
6309  if (incompressible) {
6310  cout.width(17); cout << log10(residual_adjflow[0]);
6311  if (energy) {cout.width(16); cout << log10(residual_adjflow[nDim+1]);}
6312  else {cout.width(16); cout << log10(residual_adjflow[1]);}
6313  }
6314 
6315  if (disc_adj) {
6316  cout.precision(4);
6317  cout.setf(ios::scientific, ios::floatfield);
6318  if (!turbo){
6319  if (compressible) {
6320  cout.width(14); cout << Total_Sens_Press;
6321  cout.width(14); cout << Total_Sens_AoA;
6322  }
6323  if (incompressible) {
6324  cout.width(14); cout << Total_Sens_ModVel;
6325  if (energy) {
6326  cout.width(14); cout << Total_Sens_Temp;
6327  } else {
6328  cout.width(14); cout << Total_Sens_BPressure;
6329  }
6330  }
6331  } else {
6332  cout.width(14); cout << Total_Sens_BPressure;
6333  cout.width(15); cout << Total_Sens_Temp;
6334  }
6335  }else {
6336  cout.precision(4);
6337  cout.setf(ios::scientific, ios::floatfield);
6338  cout.width(14); cout << Total_Sens_Geo;
6339  cout.width(14); cout << Total_Sens_AoA;
6340  }
6341  cout << endl;
6342  cout.unsetf(ios_base::floatfield);
6343  }
6344  }
6345  break;
6346 
6347  case ADJ_RANS : case DISC_ADJ_RANS:
6348 
6349  if (!DualTime_Iteration) {
6350  ConvHist_file[0] << begin << adjoint_coeff << adj_flow_resid;
6351  if (!frozen_visc)
6352  ConvHist_file[0] << adj_turb_resid;
6353  ConvHist_file[0] << end;
6354  ConvHist_file[0].flush();
6355  }
6356  if ((val_iZone == 0 && val_iInst == 0)|| fluid_structure){
6357  if (DualTime_Iteration || !Unsteady){
6358  cout.precision(6);
6359  cout.setf(ios::fixed, ios::floatfield);
6360  cout.width(17); cout << log10(residual_adjflow[0]);
6361  if (!frozen_visc) {
6362  cout.width(17); cout << log10(residual_adjturbulent[0]);
6363  }
6364  else {
6365  if (compressible) {
6366  if (geometry[val_iZone][val_iInst][FinestMesh]->GetnDim() == 2 ) { cout.width(15); cout << log10(residual_adjflow[3]); }
6367  else { cout.width(15); cout << log10(residual_adjflow[4]); }
6368  }
6369  if (incompressible) {
6370  if (energy) {cout.width(15); cout << log10(residual_adjflow[nDim+1]);}
6371  else {cout.width(15); cout << log10(residual_adjflow[1]);}
6372  }
6373  }
6374  if (disc_adj) {
6375  if (!turbo){
6376  if (compressible) {
6377  cout.width(14); cout << Total_Sens_Press;
6378  cout.width(14); cout << Total_Sens_AoA;
6379  }
6380  if (incompressible) {
6381  cout.width(14); cout << Total_Sens_ModVel;
6382  if (energy) {
6383  cout.width(14); cout << Total_Sens_Temp;
6384  } else {
6385  cout.width(14); cout << Total_Sens_BPressure;
6386  } }
6387  } else {
6388  cout.width(14); cout << Total_Sens_BPressure;
6389  cout.width(15); cout << Total_Sens_Temp;
6390  }
6391  }else {
6392  cout.precision(4);
6393  cout.setf(ios::scientific, ios::floatfield);
6394  cout.width(14); cout << Total_Sens_Geo;
6395  cout.width(14); cout << Total_Sens_AoA;
6396  }
6397  cout << endl;
6398  cout.unsetf(ios_base::floatfield);
6399  }
6400  }
6401  break;
6402 
6403  }
6404  cout.unsetf(ios::fixed);
6405 
6406  }
6407 
6408 
6409  delete [] residual_flow;
6410  delete [] residual_turbulent;
6411  delete [] residual_transition;
6412  delete [] residual_fea;
6413  delete [] residual_fem;
6414  delete [] residual_heat;
6415 
6416  delete [] residual_adjflow;
6417  delete [] residual_adjturbulent;
6418 
6419  delete [] Surface_CL;
6420  delete [] Surface_CD;
6421  delete [] Surface_CSF;
6422  delete [] Surface_CEff;
6423  delete [] Surface_CFx;
6424  delete [] Surface_CFy;
6425  delete [] Surface_CFz;
6426  delete [] Surface_CMx;
6427  delete [] Surface_CMy;
6428  delete [] Surface_CMz;
6429  delete [] aeroelastic_pitch;
6430  delete [] aeroelastic_plunge;
6431 
6432  }
6433 }
6434 
6435 void COutput::SetCFL_Number(CSolver *****solver_container, CConfig **config, unsigned short val_iZone) {
6436 
6437  su2double CFLFactor = 1.0, power = 1.0, CFL = 0.0, CFLMin = 0.0, CFLMax = 0.0, Div = 1.0, Diff = 0.0, MGFactor[100];
6438  unsigned short iMesh;
6439 
6440  unsigned short FinestMesh = config[val_iZone]->GetFinestMesh();
6441  unsigned long ExtIter = config[val_iZone]->GetExtIter();
6442  unsigned short nVar = 1;
6443 
6444  bool energy = config[val_iZone]->GetEnergy_Equation();
6445  bool weakly_coupled_heat = config[val_iZone]->GetWeakly_Coupled_Heat();
6446 
6447  switch( config[val_iZone]->GetKind_Solver()) {
6448  case EULER : case NAVIER_STOKES : case RANS:
6449  if (energy) {
6450  nVar = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetnVar();
6451  RhoRes_New = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetRes_RMS(nVar-1);
6452  }
6453  else if (weakly_coupled_heat) {
6454  RhoRes_New = solver_container[val_iZone][INST_0][FinestMesh][HEAT_SOL]->GetRes_RMS(0);
6455  }
6456  else {
6457  RhoRes_New = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetRes_RMS(0);
6458  }
6459  break;
6460  case ADJ_EULER : case ADJ_NAVIER_STOKES: case ADJ_RANS:
6461  RhoRes_New = solver_container[val_iZone][INST_0][FinestMesh][ADJFLOW_SOL]->GetRes_RMS(0);
6462  break;
6463  case HEAT_EQUATION_FVM:
6464  RhoRes_New = solver_container[val_iZone][INST_0][FinestMesh][HEAT_SOL]->GetRes_RMS(0);
6465  break;
6466  }
6467 
6468  if (RhoRes_New < EPS) RhoRes_New = EPS;
6469  if (RhoRes_Old[val_iZone] < EPS) RhoRes_Old[val_iZone] = RhoRes_New;
6470 
6471  Div = RhoRes_Old[val_iZone]/RhoRes_New;
6472  Diff = RhoRes_New-RhoRes_Old[val_iZone];
6473 
6474  /*--- Compute MG factor ---*/
6475 
6476  for (iMesh = 0; iMesh <= config[val_iZone]->GetnMGLevels(); iMesh++) {
6477  if (iMesh == MESH_0) MGFactor[iMesh] = 1.0;
6478  else MGFactor[iMesh] = MGFactor[iMesh-1] * config[val_iZone]->GetCFL(iMesh)/config[val_iZone]->GetCFL(iMesh-1);
6479  }
6480 
6481  if (Div < 1.0) power = config[val_iZone]->GetCFL_AdaptParam(0);
6482  else power = config[val_iZone]->GetCFL_AdaptParam(1);
6483 
6484  /*--- Detect a stall in the residual ---*/
6485 
6486  if ((fabs(Diff) <= RhoRes_New*1E-8) && (ExtIter != 0)) { Div = 0.1; power = config[val_iZone]->GetCFL_AdaptParam(1); }
6487 
6488  CFLMin = config[val_iZone]->GetCFL_AdaptParam(2);
6489  CFLMax = config[val_iZone]->GetCFL_AdaptParam(3);
6490 
6491  CFLFactor = pow(Div, power);
6492 
6493  for (iMesh = 0; iMesh <= config[val_iZone]->GetnMGLevels(); iMesh++) {
6494  CFL = config[val_iZone]->GetCFL(iMesh);
6495  CFL *= CFLFactor;
6496 
6497  if ((iMesh == MESH_0) && (CFL <= CFLMin)) {
6498  for (iMesh = 0; iMesh <= config[val_iZone]->GetnMGLevels(); iMesh++) {
6499  config[val_iZone]->SetCFL(iMesh, 1.001*CFLMin*MGFactor[iMesh]);
6500  }
6501  break;
6502  }
6503  if ((iMesh == MESH_0) && (CFL >= CFLMax)) {
6504  for (iMesh = 0; iMesh <= config[val_iZone]->GetnMGLevels(); iMesh++)
6505  config[val_iZone]->SetCFL(iMesh, 0.999*CFLMax*MGFactor[iMesh]);
6506  break;
6507  }
6508 
6509  config[val_iZone]->SetCFL(iMesh, CFL);
6510  }
6511 
6512  switch( config[val_iZone]->GetKind_Solver()) {
6513  case EULER : case NAVIER_STOKES : case RANS:
6514  nVar = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetnVar();
6515  if (energy) RhoRes_Old[val_iZone] = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetRes_RMS(nVar-1);
6516  else if (weakly_coupled_heat) RhoRes_Old[val_iZone] = solver_container[val_iZone][INST_0][FinestMesh][HEAT_SOL]->GetRes_RMS(0);
6517  else RhoRes_Old[val_iZone] = solver_container[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetRes_RMS(0);
6518  break;
6519  case ADJ_EULER : case ADJ_NAVIER_STOKES: case ADJ_RANS:
6520  RhoRes_Old[val_iZone] = solver_container[val_iZone][INST_0][FinestMesh][ADJFLOW_SOL]->GetRes_RMS(0);
6521  break;
6522  case HEAT_EQUATION_FVM:
6523  RhoRes_Old[val_iZone] = solver_container[val_iZone][INST_0][FinestMesh][HEAT_SOL]->GetRes_RMS(0);
6524  break;
6525  }
6526 
6527 }
6528 
6529 void COutput::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry ****geometry, CConfig **config, unsigned short val_iZone, bool output) {
6530 
6531  char cstr[200];
6532  unsigned short iDim, iMarker_Monitoring;
6533  ofstream Breakdown_file;
6534 
6535  bool compressible = (config[val_iZone]->GetKind_Regime() == COMPRESSIBLE);
6536  bool incompressible = (config[val_iZone]->GetKind_Regime() == INCOMPRESSIBLE);
6537  bool unsteady = (config[val_iZone]->GetUnsteady_Simulation() != NO);
6538  bool viscous = config[val_iZone]->GetViscous();
6539  bool grid_movement = config[val_iZone]->GetGrid_Movement();
6540  bool gravity = config[val_iZone]->GetGravityForce();
6541  bool turbulent = config[val_iZone]->GetKind_Solver() == RANS;
6542  bool fixed_cl = config[val_iZone]->GetFixed_CL_Mode();
6543  unsigned short Kind_Solver = config[val_iZone]->GetKind_Solver();
6544  unsigned short Kind_Regime = config[val_iZone]->GetKind_Regime();
6545  unsigned short Kind_Turb_Model = config[val_iZone]->GetKind_Turb_Model();
6546  unsigned short Ref_NonDim = config[val_iZone]->GetRef_NonDim();
6547 
6548  unsigned short FinestMesh = config[val_iZone]->GetFinestMesh();
6549  unsigned short nDim = geometry[val_iZone][INST_0][FinestMesh]->GetnDim();
6550  bool flow = ((config[val_iZone]->GetKind_Solver() == EULER) || (config[val_iZone]->GetKind_Solver() == NAVIER_STOKES) ||
6551  (config[val_iZone]->GetKind_Solver() == RANS));
6552 
6553  /*--- Output the mean flow solution using only the master node ---*/
6554 
6555  if ((rank == MASTER_NODE) && (flow) && (output)) {
6556 
6557  cout << endl << "Writing the forces breakdown file ("<< config[val_iZone]->GetBreakdown_FileName() << ")." << endl;
6558 
6559  /*--- Initialize variables to store information from all domains (direct solution) ---*/
6560 
6561  su2double Total_CL = 0.0, Total_CD = 0.0, Total_CSF = 0.0,
6562  Total_CMx = 0.0, Total_CMy = 0.0, Total_CMz = 0.0, Total_CEff = 0.0,
6563  Total_CoPx = 0.0, Total_CoPy = 0.0, Total_CoPz = 0.0,
6564  Total_CFx = 0.0, Total_CFy = 0.0, Total_CFz = 0.0, Inv_CL = 0.0,
6565  Inv_CD = 0.0, Inv_CSF = 0.0, Inv_CMx = 0.0, Inv_CMy = 0.0,
6566  Inv_CMz = 0.0, Inv_CEff = 0.0, Inv_CFx = 0.0, Inv_CFy = 0.0, Inv_CFz =
6567  0.0, Mnt_CL = 0.0,
6568  Mnt_CD = 0.0, Mnt_CSF = 0.0, Mnt_CMx = 0.0, Mnt_CMy = 0.0,
6569  Mnt_CMz = 0.0, Mnt_CEff = 0.0, Mnt_CFx = 0.0, Mnt_CFy = 0.0, Mnt_CFz =
6570  0.0, Visc_CL = 0.0,
6571  Visc_CD = 0.0, Visc_CSF = 0.0, Visc_CMx = 0.0, Visc_CMy = 0.0,
6572  Visc_CMz = 0.0, Visc_CEff = 0.0, Visc_CFx = 0.0, Visc_CFy = 0.0, Visc_CFz =
6573  0.0, *Surface_CL = NULL, *Surface_CD = NULL,
6574  *Surface_CSF = NULL, *Surface_CEff = NULL, *Surface_CFx = NULL,
6575  *Surface_CFy = NULL, *Surface_CFz = NULL,
6576  *Surface_CMx = NULL, *Surface_CMy = NULL, *Surface_CMz = NULL,
6577  *Surface_CL_Inv = NULL,
6578  *Surface_CD_Inv = NULL, *Surface_CSF_Inv = NULL,
6579  *Surface_CEff_Inv = NULL, *Surface_CFx_Inv = NULL, *Surface_CFy_Inv =
6580  NULL, *Surface_CFz_Inv = NULL, *Surface_CMx_Inv = NULL,
6581  *Surface_CMy_Inv = NULL, *Surface_CMz_Inv = NULL,
6582  *Surface_CL_Visc = NULL,
6583  *Surface_CD_Visc = NULL, *Surface_CSF_Visc = NULL,
6584  *Surface_CEff_Visc = NULL, *Surface_CFx_Visc = NULL, *Surface_CFy_Visc =
6585  NULL, *Surface_CFz_Visc = NULL, *Surface_CMx_Visc = NULL,
6586  *Surface_CMy_Visc = NULL, *Surface_CMz_Visc = NULL,
6587  *Surface_CL_Mnt = NULL,
6588  *Surface_CD_Mnt = NULL, *Surface_CSF_Mnt = NULL,
6589  *Surface_CEff_Mnt = NULL, *Surface_CFx_Mnt = NULL, *Surface_CFy_Mnt =
6590  NULL, *Surface_CFz_Mnt = NULL, *Surface_CMx_Mnt = NULL,
6591  *Surface_CMy_Mnt = NULL, *Surface_CMz_Mnt = NULL;
6592 
6593  /*--- WARNING: when compiling on Windows, ctime() is not available. Comment out
6594  the two lines below that use the dt variable. ---*/
6595  //time_t now = time(0);
6596  //string dt = ctime(&now); dt[24] = '.';
6597 
6598  /*--- Allocate memory for the coefficients being monitored ---*/
6599 
6600  Surface_CL = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6601  Surface_CD = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6602  Surface_CSF = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6603  Surface_CEff = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6604  Surface_CFx = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6605  Surface_CFy = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6606  Surface_CFz = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6607  Surface_CMx = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6608  Surface_CMy = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6609  Surface_CMz = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6610 
6611  Surface_CL_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6612  Surface_CD_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6613  Surface_CSF_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6614  Surface_CEff_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6615  Surface_CFx_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6616  Surface_CFy_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6617  Surface_CFz_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6618  Surface_CMx_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6619  Surface_CMy_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6620  Surface_CMz_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6621 
6622  Surface_CL_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6623  Surface_CD_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6624  Surface_CSF_Visc =
6625  new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6626  Surface_CEff_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6627  Surface_CFx_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6628  Surface_CFy_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6629  Surface_CFz_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6630  Surface_CMx_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6631  Surface_CMy_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6632  Surface_CMz_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6633 
6634 
6635  Surface_CL_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6636  Surface_CD_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6637  Surface_CSF_Mnt =
6638  new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6639  Surface_CEff_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6640  Surface_CFx_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6641  Surface_CFy_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6642  Surface_CFz_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6643  Surface_CMx_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6644  Surface_CMy_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6645  Surface_CMz_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()];
6646 
6647  /*--- Flow solution coefficients ---*/
6648 
6649  Total_CL = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CL();
6650  Total_CD = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CD();
6651  Total_CSF = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CSF();
6652  Total_CEff = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CEff();
6653  Total_CMx = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CMx();
6654  Total_CMy = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CMy();
6655  Total_CMz = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CMz();
6656  Total_CFx = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFx();
6657  Total_CFy = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFy();
6658  Total_CFz = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFz();
6659 
6660  if (nDim == 2) {
6661  Total_CoPx = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CoPx() / solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFy();
6662  Total_CoPy = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CoPy() / solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFx();
6663  Total_CoPz = 0.0;
6664  }
6665  if (nDim == 3) {
6666  Total_CoPx = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CoPx() / solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFz();
6667  Total_CoPy = 0.0;
6668  Total_CoPz = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CoPz() / solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFx();
6669  }
6670 
6671  if (config[ZONE_0]->GetSystemMeasurements() == US) { Total_CoPx *= 12.0; Total_CoPy *= 12.0; Total_CoPz *= 12.0; }
6672 
6673  /*--- Flow inviscid solution coefficients ---*/
6674 
6675  Inv_CL =
6676  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CL_Inv();
6677  Inv_CD =
6678  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CD_Inv();
6679  Inv_CSF =
6680  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CSF_Inv();
6681  Inv_CEff =
6682  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CEff_Inv();
6683  Inv_CMx =
6684  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMx_Inv();
6685  Inv_CMy =
6686  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMy_Inv();
6687  Inv_CMz =
6688  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMz_Inv();
6689  Inv_CFx =
6690  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFx_Inv();
6691  Inv_CFy =
6692  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFy_Inv();
6693  Inv_CFz =
6694  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFz_Inv();
6695 
6696  /*--- Flow viscous solution coefficients ---*/
6697 
6698  Visc_CL =
6699  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CL_Visc();
6700  Visc_CD =
6701  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CD_Visc();
6702  Visc_CSF =
6703  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CSF_Visc();
6704  Visc_CEff =
6705  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CEff_Visc();
6706  Visc_CMx =
6707  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMx_Visc();
6708  Visc_CMy =
6709  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMy_Visc();
6710  Visc_CMz =
6711  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMz_Visc();
6712  Visc_CFx =
6713  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFx_Visc();
6714  Visc_CFy =
6715  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFy_Visc();
6716  Visc_CFz =
6717  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFz_Visc();
6718 
6719  /*--- Flow momentum solution coefficients ---*/
6720 
6721  Mnt_CL =
6722  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CL_Mnt();
6723  Mnt_CD =
6724  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CD_Mnt();
6725  Mnt_CSF =
6726  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CSF_Mnt();
6727  Mnt_CEff =
6728  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CEff_Mnt();
6729  Mnt_CMx =
6730  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMx_Mnt();
6731  Mnt_CMy =
6732  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMy_Mnt();
6733  Mnt_CMz =
6734  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CMz_Mnt();
6735  Mnt_CFx =
6736  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFx_Mnt();
6737  Mnt_CFy =
6738  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFy_Mnt();
6739  Mnt_CFz =
6740  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFz_Mnt();
6741 
6742 
6743  /*--- Look over the markers being monitored and get the desired values ---*/
6744 
6745  for (iMarker_Monitoring = 0;
6746  iMarker_Monitoring < config[ZONE_0]->GetnMarker_Monitoring();
6747  iMarker_Monitoring++) {
6748  Surface_CL[iMarker_Monitoring] =
6749  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CL(
6750  iMarker_Monitoring);
6751  Surface_CD[iMarker_Monitoring] =
6752  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CD(
6753  iMarker_Monitoring);
6754  Surface_CSF[iMarker_Monitoring] =
6755  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CSF(
6756  iMarker_Monitoring);
6757  Surface_CEff[iMarker_Monitoring] =
6758  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CEff(
6759  iMarker_Monitoring);
6760  Surface_CMx[iMarker_Monitoring] =
6761  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMx(
6762  iMarker_Monitoring);
6763  Surface_CMy[iMarker_Monitoring] =
6764  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMy(
6765  iMarker_Monitoring);
6766  Surface_CMz[iMarker_Monitoring] =
6767  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMz(
6768  iMarker_Monitoring);
6769  Surface_CFx[iMarker_Monitoring] =
6770  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFx(
6771  iMarker_Monitoring);
6772  Surface_CFy[iMarker_Monitoring] =
6773  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFy(
6774  iMarker_Monitoring);
6775  Surface_CFz[iMarker_Monitoring] =
6776  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFz(
6777  iMarker_Monitoring);
6778 
6779  Surface_CL_Inv[iMarker_Monitoring] =
6780  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CL_Inv(
6781  iMarker_Monitoring);
6782  Surface_CD_Inv[iMarker_Monitoring] =
6783  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CD_Inv(
6784  iMarker_Monitoring);
6785  Surface_CSF_Inv[iMarker_Monitoring] =
6786  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CSF_Inv(
6787  iMarker_Monitoring);
6788  Surface_CEff_Inv[iMarker_Monitoring] =
6789  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CEff_Inv(
6790  iMarker_Monitoring);
6791  Surface_CMx_Inv[iMarker_Monitoring] =
6792  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMx_Inv(
6793  iMarker_Monitoring);
6794  Surface_CMy_Inv[iMarker_Monitoring] =
6795  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMy_Inv(
6796  iMarker_Monitoring);
6797  Surface_CMz_Inv[iMarker_Monitoring] =
6798  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMz_Inv(
6799  iMarker_Monitoring);
6800  Surface_CFx_Inv[iMarker_Monitoring] =
6801  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFx_Inv(
6802  iMarker_Monitoring);
6803  Surface_CFy_Inv[iMarker_Monitoring] =
6804  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFy_Inv(
6805  iMarker_Monitoring);
6806  Surface_CFz_Inv[iMarker_Monitoring] =
6807  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFz_Inv(
6808  iMarker_Monitoring);
6809  Surface_CL_Visc[iMarker_Monitoring] =
6810  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CL_Visc(
6811  iMarker_Monitoring);
6812  Surface_CD_Visc[iMarker_Monitoring] =
6813  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CD_Visc(
6814  iMarker_Monitoring);
6815  Surface_CSF_Visc[iMarker_Monitoring] =
6816  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CSF_Visc(
6817  iMarker_Monitoring);
6818  Surface_CEff_Visc[iMarker_Monitoring] =
6819  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CEff_Visc(
6820  iMarker_Monitoring);
6821  Surface_CMx_Visc[iMarker_Monitoring] =
6822  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMx_Visc(
6823  iMarker_Monitoring);
6824  Surface_CMy_Visc[iMarker_Monitoring] =
6825  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMy_Visc(
6826  iMarker_Monitoring);
6827  Surface_CMz_Visc[iMarker_Monitoring] =
6828  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMz_Visc(
6829  iMarker_Monitoring);
6830  Surface_CFx_Visc[iMarker_Monitoring] =
6831  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFx_Visc(
6832  iMarker_Monitoring);
6833  Surface_CFy_Visc[iMarker_Monitoring] =
6834  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFy_Visc(
6835  iMarker_Monitoring);
6836  Surface_CFz_Visc[iMarker_Monitoring] =
6837  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFz_Visc(
6838  iMarker_Monitoring);
6839 
6840  Surface_CL_Mnt[iMarker_Monitoring] =
6841  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CL_Mnt(
6842  iMarker_Monitoring);
6843  Surface_CD_Mnt[iMarker_Monitoring] =
6844  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CD_Mnt(
6845  iMarker_Monitoring);
6846  Surface_CSF_Mnt[iMarker_Monitoring] =
6847  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CSF_Mnt(
6848  iMarker_Monitoring);
6849  Surface_CEff_Mnt[iMarker_Monitoring] =
6850  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CEff_Mnt(
6851  iMarker_Monitoring);
6852  Surface_CMx_Mnt[iMarker_Monitoring] =
6853  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMx_Mnt(
6854  iMarker_Monitoring);
6855  Surface_CMy_Mnt[iMarker_Monitoring] =
6856  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMy_Mnt(
6857  iMarker_Monitoring);
6858  Surface_CMz_Mnt[iMarker_Monitoring] =
6859  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CMz_Mnt(
6860  iMarker_Monitoring);
6861  Surface_CFx_Mnt[iMarker_Monitoring] =
6862  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFx_Mnt(
6863  iMarker_Monitoring);
6864  Surface_CFy_Mnt[iMarker_Monitoring] =
6865  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFy_Mnt(
6866  iMarker_Monitoring);
6867  Surface_CFz_Mnt[iMarker_Monitoring] =
6868  solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFz_Mnt(
6869  iMarker_Monitoring);
6870 
6871  }
6872 
6873 
6874  /*--- Write file name with extension ---*/
6875 
6876  string filename = config[val_iZone]->GetBreakdown_FileName();
6877  strcpy (cstr, filename.data());
6878 
6879  Breakdown_file.open(cstr, ios::out);
6880 
6881  Breakdown_file << "\n" <<"-------------------------------------------------------------------------" << "\n";
6882  Breakdown_file <<"| ___ _ _ ___ |" << "\n";
6883  Breakdown_file <<"| / __| | | |_ ) Release 6.1.0 \"Falcon\" |" << "\n";
6884  Breakdown_file <<"| \\__ \\ |_| |/ / |" << "\n";
6885  Breakdown_file <<"| |___/\\___//___| Suite (Computational Fluid Dynamics Code) |" << "\n";
6886  Breakdown_file << "| |" << "\n";
6887  //Breakdown_file << "| Local date and time: " << dt << " |" << "\n";
6888  Breakdown_file <<"-------------------------------------------------------------------------" << "\n";
6889  Breakdown_file << "| The current SU2 release has been coordinated by the |" << "\n";
6890  Breakdown_file << "| SU2 International Developers Society <www.su2devsociety.org> |" << "\n";
6891  Breakdown_file << "| with selected contributions from the open-source community |" << "\n";
6892  Breakdown_file <<"-------------------------------------------------------------------------" << "\n";
6893  Breakdown_file << "| The main research teams contributing to the current release are: |" << "\n";
6894  Breakdown_file << "| - Prof. Juan J. Alonso's group at Stanford University. |" << "\n";
6895  Breakdown_file << "| - Prof. Piero Colonna's group at Delft University of Technology. |" << "\n";
6896  Breakdown_file << "| - Prof. Nicolas R. Gauger's group at Kaiserslautern U. of Technology. |" << "\n";
6897  Breakdown_file << "| - Prof. Alberto Guardone's group at Polytechnic University of Milan. |" << "\n";
6898  Breakdown_file << "| - Prof. Rafael Palacios' group at Imperial College London. |" << "\n";
6899  Breakdown_file << "| - Prof. Vincent Terrapon's group at the University of Liege. |" << "\n";
6900  Breakdown_file << "| - Prof. Edwin van der Weide's group at the University of Twente. |" << "\n";
6901  Breakdown_file << "| - Lab. of New Concepts in Aeronautics at Tech. Inst. of Aeronautics. |" << "\n";
6902  Breakdown_file <<"-------------------------------------------------------------------------" << "\n";
6903  Breakdown_file << "| Copyright 2012-2018, Francisco D. Palacios, Thomas D. Economon, |" << "\n";
6904  Breakdown_file << "| Tim Albring, and the SU2 contributors. |" << "\n";
6905  Breakdown_file << "| |" << "\n";
6906  Breakdown_file << "| SU2 is free software; you can redistribute it and/or |" << "\n";
6907  Breakdown_file << "| modify it under the terms of the GNU Lesser General Public |" << "\n";
6908  Breakdown_file << "| License as published by the Free Software Foundation; either |" << "\n";
6909  Breakdown_file << "| version 2.1 of the License, or (at your option) any later version. |" << "\n";
6910  Breakdown_file << "| |" << "\n";
6911  Breakdown_file << "| SU2 is distributed in the hope that it will be useful, |" << "\n";
6912  Breakdown_file << "| but WITHOUT ANY WARRANTY; without even the implied warranty of |" << "\n";
6913  Breakdown_file << "| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |" << "\n";
6914  Breakdown_file << "| Lesser General Public License for more details. |" << "\n";
6915  Breakdown_file << "| |" << "\n";
6916  Breakdown_file << "| You should have received a copy of the GNU Lesser General Public |" << "\n";
6917  Breakdown_file << "| License along with SU2. If not, see <http://www.gnu.org/licenses/>. |" << "\n";
6918  Breakdown_file <<"-------------------------------------------------------------------------" << "\n";
6919 
6920  Breakdown_file.precision(6);
6921 
6922  Breakdown_file << "\n" << "\n" << "Problem definition:" << "\n" << "\n";
6923 
6924  switch (Kind_Solver) {
6925  case EULER:
6926  if (Kind_Regime == COMPRESSIBLE) Breakdown_file << "Compressible Euler equations." << "\n";
6927  if (Kind_Regime == INCOMPRESSIBLE) Breakdown_file << "Incompressible Euler equations." << "\n";
6928  break;
6929  case NAVIER_STOKES:
6930  if (Kind_Regime == COMPRESSIBLE) Breakdown_file << "Compressible Laminar Navier-Stokes' equations." << "\n";
6931  if (Kind_Regime == INCOMPRESSIBLE) Breakdown_file << "Incompressible Laminar Navier-Stokes' equations." << "\n";
6932  break;
6933  case RANS:
6934  if (Kind_Regime == COMPRESSIBLE) Breakdown_file << "Compressible RANS equations." << "\n";
6935  if (Kind_Regime == INCOMPRESSIBLE) Breakdown_file << "Incompressible RANS equations." << "\n";
6936  Breakdown_file << "Turbulence model: ";
6937  switch (Kind_Turb_Model) {
6938  case SA: Breakdown_file << "Spalart Allmaras" << "\n"; break;
6939  case SA_NEG: Breakdown_file << "Negative Spalart Allmaras" << "\n"; break;
6940  case SST: Breakdown_file << "Menter's SST" << "\n"; break;
6941  }
6942  break;
6943  }
6944 
6945 
6946  /*--- Compressible version of console output ---*/
6947 
6948  if (compressible) {
6949 
6950 
6951  if ((Kind_Regime == COMPRESSIBLE) && (Kind_Solver != FEM_ELASTICITY)) {
6952  Breakdown_file << "Mach number: " << config[val_iZone]->GetMach() <<"."<< "\n";
6953  Breakdown_file << "Angle of attack (AoA): " << config[val_iZone]->GetAoA() <<" deg, and angle of sideslip (AoS): " << config[val_iZone]->GetAoS() <<" deg."<< "\n";
6954  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == ADJ_NAVIER_STOKES) ||
6955  (Kind_Solver == RANS) || (Kind_Solver == ADJ_RANS))
6956  Breakdown_file << "Reynolds number: " << config[val_iZone]->GetReynolds() <<"."<< "\n";
6957  }
6958 
6959  if (fixed_cl) {
6960  Breakdown_file << "Simulation at a cte. CL: " << config[val_iZone]->GetTarget_CL() << ".\n";
6961  Breakdown_file << "Approx. Delta CL / Delta AoA: " << config[val_iZone]->GetdCL_dAlpha() << " (1/deg).\n";
6962  Breakdown_file << "Approx. Delta CD / Delta CL: " << config[val_iZone]->GetdCD_dCL() << ".\n";
6963  if (nDim == 3 ) {
6964  Breakdown_file << "Approx. Delta CMx / Delta CL: " << config[val_iZone]->GetdCMx_dCL() << ".\n";
6965  Breakdown_file << "Approx. Delta CMy / Delta CL: " << config[val_iZone]->GetdCMy_dCL() << ".\n";
6966  }
6967  Breakdown_file << "Approx. Delta CMz / Delta CL: " << config[val_iZone]->GetdCMz_dCL() << ".\n";
6968  }
6969 
6970  if (Ref_NonDim == DIMENSIONAL) { Breakdown_file << "Dimensional simulation." << "\n"; }
6971  else if (Ref_NonDim == FREESTREAM_PRESS_EQ_ONE) { Breakdown_file << "Non-Dimensional simulation (P=1.0, Rho=1.0, T=1.0 at the farfield)." << "\n"; }
6972  else if (Ref_NonDim == FREESTREAM_VEL_EQ_MACH) { Breakdown_file << "Non-Dimensional simulation (V=Mach, Rho=1.0, T=1.0 at the farfield)." << "\n"; }
6973  else if (Ref_NonDim == FREESTREAM_VEL_EQ_ONE) { Breakdown_file << "Non-Dimensional simulation (V=1.0, Rho=1.0, T=1.0 at the farfield)." << "\n"; }
6974 
6975  if (config[val_iZone]->GetSystemMeasurements() == SI) {
6976  Breakdown_file << "The reference area is " << config[val_iZone]->GetRefArea() << " m^2." << "\n";
6977  Breakdown_file << "The reference length is " << config[val_iZone]->GetRefLength() << " m." << "\n";
6978  }
6979 
6980  if (config[val_iZone]->GetSystemMeasurements() == US) {
6981  Breakdown_file << "The reference area is " << config[val_iZone]->GetRefArea()*12.0*12.0 << " in^2." << "\n";
6982  Breakdown_file << "The reference length is " << config[val_iZone]->GetRefLength()*12.0 << " in." << "\n";
6983  }
6984  Breakdown_file << "\n" << "\n" <<"Problem definition:" << "\n" << "\n";
6985  if (compressible) {
6986  if (viscous) {
6987  Breakdown_file << "Viscous flow: Computing pressure using the ideal gas law" << "\n";
6988  Breakdown_file << "based on the free-stream temperature and a density computed" << "\n";
6989  Breakdown_file << "from the Reynolds number." << "\n";
6990  } else {
6991  Breakdown_file << "Inviscid flow: Computing density based on free-stream" << "\n";
6992  Breakdown_file << "temperature and pressure using the ideal gas law." << "\n";
6993  }
6994  }
6995 
6996  if (grid_movement) Breakdown_file << "Force coefficients computed using MACH_MOTION." << "\n";
6997  else Breakdown_file << "Force coefficients computed using free-stream values." << "\n";
6998 
6999  if (incompressible) {
7000  Breakdown_file << "Viscous and Inviscid flow: rho_ref, and vel_ref" << "\n";
7001  Breakdown_file << "are based on the free-stream values, p_ref = rho_ref*vel_ref^2." << "\n";
7002  Breakdown_file << "The free-stream value of the pressure is 0." << "\n";
7003  Breakdown_file << "Mach number: "<< config[val_iZone]->GetMach() << ", computed using the Bulk modulus." << "\n";
7004  Breakdown_file << "Angle of attack (deg): "<< config[val_iZone]->GetAoA() << ", computed using the the free-stream velocity." << "\n";
7005  Breakdown_file << "Side slip angle (deg): "<< config[val_iZone]->GetAoS() << ", computed using the the free-stream velocity." << "\n";
7006  if (viscous) Breakdown_file << "Reynolds number: " << config[val_iZone]->GetReynolds() << ", computed using free-stream values."<< "\n";
7007  Breakdown_file << "Only dimensional computation, the grid should be dimensional." << "\n";
7008  }
7009 
7010  Breakdown_file <<"-- Input conditions:"<< "\n";
7011 
7012  if (compressible) {
7013  switch (config[val_iZone]->GetKind_FluidModel()) {
7014 
7015  case STANDARD_AIR:
7016  Breakdown_file << "Fluid Model: STANDARD_AIR "<< "\n";
7017  Breakdown_file << "Specific gas constant: " << config[val_iZone]->GetGas_Constant();
7018  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.m/kg.K." << "\n";
7019  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.ft/slug.R." << "\n";
7020  Breakdown_file << "Specific gas constant (non-dim): " << config[val_iZone]->GetGas_ConstantND()<< "\n";
7021  Breakdown_file << "Specific Heat Ratio: 1.4000 "<< "\n";
7022  break;
7023 
7024  case IDEAL_GAS:
7025  Breakdown_file << "Fluid Model: IDEAL_GAS "<< "\n";
7026  Breakdown_file << "Specific gas constant: " << config[val_iZone]->GetGas_Constant() << " N.m/kg.K." << "\n";
7027  Breakdown_file << "Specific gas constant (non-dim): " << config[val_iZone]->GetGas_ConstantND()<< "\n";
7028  Breakdown_file << "Specific Heat Ratio: "<< config[val_iZone]->GetGamma() << "\n";
7029  break;
7030 
7031  case VW_GAS:
7032  Breakdown_file << "Fluid Model: Van der Waals "<< "\n";
7033  Breakdown_file << "Specific gas constant: " << config[val_iZone]->GetGas_Constant() << " N.m/kg.K." << "\n";
7034  Breakdown_file << "Specific gas constant (non-dim): " << config[val_iZone]->GetGas_ConstantND()<< "\n";
7035  Breakdown_file << "Specific Heat Ratio: "<< config[val_iZone]->GetGamma() << "\n";
7036  Breakdown_file << "Critical Pressure: " << config[val_iZone]->GetPressure_Critical() << " Pa." << "\n";
7037  Breakdown_file << "Critical Temperature: " << config[val_iZone]->GetTemperature_Critical() << " K." << "\n";
7038  Breakdown_file << "Critical Pressure (non-dim): " << config[val_iZone]->GetPressure_Critical() /config[val_iZone]->GetPressure_Ref() << "\n";
7039  Breakdown_file << "Critical Temperature (non-dim) : " << config[val_iZone]->GetTemperature_Critical() /config[val_iZone]->GetTemperature_Ref() << "\n";
7040  break;
7041 
7042  case PR_GAS:
7043  Breakdown_file << "Fluid Model: Peng-Robinson "<< "\n";
7044  Breakdown_file << "Specific gas constant: " << config[val_iZone]->GetGas_Constant() << " N.m/kg.K." << "\n";
7045  Breakdown_file << "Specific gas constant(non-dim): " << config[val_iZone]->GetGas_ConstantND()<< "\n";
7046  Breakdown_file << "Specific Heat Ratio: "<< config[val_iZone]->GetGamma() << "\n";
7047  Breakdown_file << "Critical Pressure: " << config[val_iZone]->GetPressure_Critical() << " Pa." << "\n";
7048  Breakdown_file << "Critical Temperature: " << config[val_iZone]->GetTemperature_Critical() << " K." << "\n";
7049  Breakdown_file << "Critical Pressure (non-dim): " << config[val_iZone]->GetPressure_Critical() /config[val_iZone]->GetPressure_Ref() << "\n";
7050  Breakdown_file << "Critical Temperature (non-dim) : " << config[val_iZone]->GetTemperature_Critical() /config[val_iZone]->GetTemperature_Ref() << "\n";
7051  break;
7052  }
7053 
7054  if (viscous) {
7055 
7056  switch (config[val_iZone]->GetKind_ViscosityModel()) {
7057 
7058  case CONSTANT_VISCOSITY:
7059  Breakdown_file << "Viscosity Model: CONSTANT_VISCOSITY "<< "\n";
7060  Breakdown_file << "Laminar Viscosity: " << config[val_iZone]->GetMu_Constant();
7061  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n";
7062  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n";
7063  Breakdown_file << "Laminar Viscosity (non-dim): " << config[val_iZone]->GetMu_ConstantND()<< "\n";
7064  break;
7065 
7066  case SUTHERLAND:
7067  Breakdown_file << "Viscosity Model: SUTHERLAND "<< "\n";
7068  Breakdown_file << "Ref. Laminar Viscosity: " << config[val_iZone]->GetMu_Ref();
7069  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n";
7070  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n";
7071  Breakdown_file << "Ref. Temperature: " << config[val_iZone]->GetMu_Temperature_Ref();
7072  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
7073  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
7074  Breakdown_file << "Sutherland Constant: "<< config[val_iZone]->GetMu_S();
7075  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
7076  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
7077  Breakdown_file << "Laminar Viscosity (non-dim): " << config[val_iZone]->GetMu_ConstantND()<< "\n";
7078  Breakdown_file << "Ref. Temperature (non-dim): " << config[val_iZone]->GetMu_Temperature_RefND()<< "\n";
7079  Breakdown_file << "Sutherland constant (non-dim): "<< config[val_iZone]->GetMu_SND()<< "\n";
7080  break;
7081 
7082  }
7083  switch (config[val_iZone]->GetKind_ConductivityModel()) {
7084 
7085  case CONSTANT_PRANDTL:
7086  Breakdown_file << "Conductivity Model: CONSTANT_PRANDTL "<< "\n";
7087  Breakdown_file << "Prandtl: " << config[val_iZone]->GetPrandtl_Lam()<< "\n";
7088  break;
7089 
7090  case CONSTANT_CONDUCTIVITY:
7091  Breakdown_file << "Conductivity Model: CONSTANT_CONDUCTIVITY "<< "\n";
7092  Breakdown_file << "Molecular Conductivity: " << config[val_iZone]->GetKt_Constant()<< " W/m^2.K." << "\n";
7093  Breakdown_file << "Molecular Conductivity (non-dim): " << config[val_iZone]->GetKt_ConstantND()<< "\n";
7094  break;
7095 
7096  }
7097  }
7098  }
7099 
7100  if (incompressible) {
7101  Breakdown_file << "Bulk modulus: " << config[val_iZone]->GetBulk_Modulus();
7102  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
7103  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
7104  Breakdown_file << "Epsilon^2 multiplier of Beta for incompressible preconditioner: " << config[val_iZone]->GetBeta_Factor();
7105  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
7106  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
7107  }
7108 
7109  Breakdown_file << "Free-stream static pressure: " << config[val_iZone]->GetPressure_FreeStream();
7110  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
7111  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
7112 
7113  Breakdown_file << "Free-stream total pressure: " << config[val_iZone]->GetPressure_FreeStream() * pow( 1.0+config[val_iZone]->GetMach()*config[val_iZone]->GetMach()*0.5*(config[val_iZone]->GetGamma()-1.0), config[val_iZone]->GetGamma()/(config[val_iZone]->GetGamma()-1.0) );
7114  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
7115  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
7116 
7117  if (compressible) {
7118  Breakdown_file << "Free-stream temperature: " << config[val_iZone]->GetTemperature_FreeStream();
7119  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
7120  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
7121 
7122  Breakdown_file << "Free-stream total temperature: " << config[val_iZone]->GetTemperature_FreeStream() * (1.0 + config[val_iZone]->GetMach() * config[val_iZone]->GetMach() * 0.5 * (config[val_iZone]->GetGamma() - 1.0));
7123  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
7124  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
7125  }
7126 
7127  Breakdown_file << "Free-stream density: " << config[val_iZone]->GetDensity_FreeStream();
7128  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " kg/m^3." << "\n";
7129  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " slug/ft^3." << "\n";
7130 
7131  if (nDim == 2) {
7132  Breakdown_file << "Free-stream velocity: (" << config[val_iZone]->GetVelocity_FreeStream()[0] << ", ";
7133  Breakdown_file << config[val_iZone]->GetVelocity_FreeStream()[1] << ")";
7134  }
7135  if (nDim == 3) {
7136  Breakdown_file << "Free-stream velocity: (" << config[val_iZone]->GetVelocity_FreeStream()[0] << ", ";
7137  Breakdown_file << config[val_iZone]->GetVelocity_FreeStream()[1] << ", " << config[val_iZone]->GetVelocity_FreeStream()[2] << ")";
7138  }
7139  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m/s. ";
7140  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft/s. ";
7141 
7142  Breakdown_file << "Magnitude: " << config[val_iZone]->GetModVel_FreeStream();
7143  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m/s." << "\n";
7144  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft/s." << "\n";
7145 
7146  if (compressible) {
7147  Breakdown_file << "Free-stream total energy per unit mass: " << config[val_iZone]->GetEnergy_FreeStream();
7148  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m^2/s^2." << "\n";
7149  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft^2/s^2." << "\n";
7150  }
7151 
7152  if (viscous) {
7153  Breakdown_file << "Free-stream viscosity: " << config[val_iZone]->GetViscosity_FreeStream();
7154  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n";
7155  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n";
7156  if (turbulent) {
7157  Breakdown_file << "Free-stream turb. kinetic energy per unit mass: " << config[val_iZone]->GetTke_FreeStream();
7158  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m^2/s^2." << "\n";
7159  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft^2/s^2." << "\n";
7160  Breakdown_file << "Free-stream specific dissipation: " << config[val_iZone]->GetOmega_FreeStream();
7161  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " 1/s." << "\n";
7162  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " 1/s." << "\n";
7163  }
7164  }
7165 
7166  if (unsteady) { Breakdown_file << "Total time: " << config[val_iZone]->GetTotal_UnstTime() << " s. Time step: " << config[val_iZone]->GetDelta_UnstTime() << " s." << "\n"; }
7167 
7168  /*--- Print out reference values. ---*/
7169 
7170  Breakdown_file <<"-- Reference values:"<< "\n";
7171 
7172  if (compressible) {
7173  Breakdown_file << "Reference specific gas constant: " << config[val_iZone]->GetGas_Constant_Ref();
7174  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.m/kg.K." << "\n";
7175  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.ft/slug.R." << "\n";
7176  }
7177 
7178  Breakdown_file << "Reference pressure: " << config[val_iZone]->GetPressure_Ref();
7179  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
7180  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
7181 
7182  if (compressible) {
7183  Breakdown_file << "Reference temperature: " << config[val_iZone]->GetTemperature_Ref();
7184  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
7185  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
7186  }
7187 
7188  Breakdown_file << "Reference density: " << config[val_iZone]->GetDensity_Ref();
7189  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " kg/m^3." << "\n";
7190  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " slug/ft^3." << "\n";
7191 
7192  Breakdown_file << "Reference velocity: " << config[val_iZone]->GetVelocity_Ref();
7193  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m/s." << "\n";
7194  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft/s." << "\n";
7195 
7196  if (compressible) {
7197  Breakdown_file << "Reference energy per unit mass: " << config[val_iZone]->GetEnergy_Ref();
7198  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m^2/s^2." << "\n";
7199  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft^2/s^2." << "\n";
7200  }
7201 
7202  if (incompressible) {
7203  Breakdown_file << "Reference length: " << config[val_iZone]->GetLength_Ref();
7204  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m." << "\n";
7205  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " in." << "\n";
7206  }
7207 
7208  if (viscous) {
7209  Breakdown_file << "Reference viscosity: " << config[val_iZone]->GetViscosity_Ref();
7210  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n";
7211  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n";
7212  if (compressible){
7213  Breakdown_file << "Reference conductivity: " << config[val_iZone]->GetConductivity_Ref();
7214  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " W/m^2.K." << "\n";
7215  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf/ft.s.R." << "\n";
7216  }
7217  }
7218 
7219 
7220  if (unsteady) Breakdown_file << "Reference time: " << config[val_iZone]->GetTime_Ref() <<" s." << "\n";
7221 
7222  /*--- Print out resulting non-dim values here. ---*/
7223 
7224  Breakdown_file << "-- Resulting non-dimensional state:" << "\n";
7225  Breakdown_file << "Mach number (non-dim): " << config[val_iZone]->GetMach() << "\n";
7226  if (viscous) {
7227  Breakdown_file << "Reynolds number (non-dim): " << config[val_iZone]->GetReynolds() <<". Re length: " << config[val_iZone]->GetLength_Reynolds();
7228  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m." << "\n";
7229  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft." << "\n";
7230  }
7231  if (gravity) {
7232  Breakdown_file << "Froude number (non-dim): " << config[val_iZone]->GetFroude() << "\n";
7233  Breakdown_file << "Lenght of the baseline wave (non-dim): " << 2.0*PI_NUMBER*config[val_iZone]->GetFroude()*config[val_iZone]->GetFroude() << "\n";
7234  }
7235 
7236  if (compressible) {
7237  Breakdown_file << "Specific gas constant (non-dim): " << config[val_iZone]->GetGas_ConstantND() << "\n";
7238  Breakdown_file << "Free-stream temperature (non-dim): " << config[val_iZone]->GetTemperature_FreeStreamND() << "\n";
7239  }
7240 
7241  Breakdown_file << "Free-stream pressure (non-dim): " << config[val_iZone]->GetPressure_FreeStreamND() << "\n";
7242 
7243  Breakdown_file << "Free-stream density (non-dim): " << config[val_iZone]->GetDensity_FreeStreamND() << "\n";
7244 
7245  if (nDim == 2) {
7246  Breakdown_file << "Free-stream velocity (non-dim): (" << config[val_iZone]->GetVelocity_FreeStreamND()[0] << ", ";
7247  Breakdown_file << config[val_iZone]->GetVelocity_FreeStreamND()[1] << "). ";
7248  } else {
7249  Breakdown_file << "Free-stream velocity (non-dim): (" << config[val_iZone]->GetVelocity_FreeStreamND()[0] << ", ";
7250  Breakdown_file << config[val_iZone]->GetVelocity_FreeStreamND()[1] << ", " << config[val_iZone]->GetVelocity_FreeStreamND()[2] << "). ";
7251  }
7252  Breakdown_file << "Magnitude: " << config[val_iZone]->GetModVel_FreeStreamND() << "\n";
7253 
7254  if (compressible)
7255  Breakdown_file << "Free-stream total energy per unit mass (non-dim): " << config[val_iZone]->GetEnergy_FreeStreamND() << "\n";
7256 
7257  if (viscous) {
7258  Breakdown_file << "Free-stream viscosity (non-dim): " << config[val_iZone]->GetViscosity_FreeStreamND() << "\n";
7259  if (turbulent) {
7260  Breakdown_file << "Free-stream turb. kinetic energy (non-dim): " << config[val_iZone]->GetTke_FreeStreamND() << "\n";
7261  Breakdown_file << "Free-stream specific dissipation (non-dim): " << config[val_iZone]->GetOmega_FreeStreamND() << "\n";
7262  }
7263  }
7264 
7265  if (unsteady) {
7266  Breakdown_file << "Total time (non-dim): " << config[val_iZone]->GetTotal_UnstTimeND() << "\n";
7267  Breakdown_file << "Time step (non-dim): " << config[val_iZone]->GetDelta_UnstTimeND() << "\n";
7268  }
7269 
7270  } else {
7271 
7272  /*--- Incompressible version of the console output ---*/
7273 
7274  bool energy = config[val_iZone]->GetEnergy_Equation();
7275  bool boussinesq = (config[val_iZone]->GetKind_DensityModel() == BOUSSINESQ);
7276 
7277  if (config[val_iZone]->GetRef_Inc_NonDim() == DIMENSIONAL) {
7278  Breakdown_file << "Viscous and Inviscid flow: rho_ref, vel_ref, temp_ref, p_ref" << "\n";
7279  Breakdown_file << "are set to 1.0 in order to perform a dimensional calculation." << "\n";
7280  if (grid_movement) Breakdown_file << "Force coefficients computed using MACH_MOTION." << "\n";
7281  else Breakdown_file << "Force coefficients computed using initial values." << "\n";
7282  }
7283  else if (config[val_iZone]->GetRef_Inc_NonDim() == INITIAL_VALUES) {
7284  Breakdown_file << "Viscous and Inviscid flow: rho_ref, vel_ref, and temp_ref" << "\n";
7285  Breakdown_file << "are based on the initial values, p_ref = rho_ref*vel_ref^2." << "\n";
7286  if (grid_movement) Breakdown_file << "Force coefficients computed using MACH_MOTION." << "\n";
7287  else Breakdown_file << "Force coefficients computed using initial values." << "\n";
7288  }
7289  else if (config[val_iZone]->GetRef_Inc_NonDim() == REFERENCE_VALUES) {
7290  Breakdown_file << "Viscous and Inviscid flow: rho_ref, vel_ref, and temp_ref" << "\n";
7291  Breakdown_file << "are user-provided reference values, p_ref = rho_ref*vel_ref^2." << "\n";
7292  if (grid_movement) Breakdown_file << "Force coefficients computed using MACH_MOTION." << "\n";
7293  else Breakdown_file << "Force coefficients computed using reference values." << "\n";
7294  }
7295  Breakdown_file << "The reference area for force coeffs. is " << config[val_iZone]->GetRefArea() << " m^2." << "\n";
7296  Breakdown_file << "The reference length for force coeffs. is " << config[val_iZone]->GetRefLength() << " m." << "\n";
7297 
7298  Breakdown_file << "The pressure is decomposed into thermodynamic and dynamic components." << "\n";
7299  Breakdown_file << "The initial value of the dynamic pressure is 0." << "\n";
7300 
7301  Breakdown_file << "Mach number: "<< config[val_iZone]->GetMach();
7302  if (config[val_iZone]->GetKind_FluidModel() == CONSTANT_DENSITY) {
7303  Breakdown_file << ", computed using the Bulk modulus." << "\n";
7304  } else {
7305  Breakdown_file << ", computed using fluid speed of sound." << "\n";
7306  }
7307 
7308  Breakdown_file << "For external flows, the initial state is imposed at the far-field." << "\n";
7309  Breakdown_file << "Angle of attack (deg): "<< config[val_iZone]->GetAoA() << ", computed using the initial velocity." << "\n";
7310  Breakdown_file << "Side slip angle (deg): "<< config[val_iZone]->GetAoS() << ", computed using the initial velocity." << "\n";
7311 
7312  if (viscous) {
7313  Breakdown_file << "Reynolds number per meter: " << config[val_iZone]->GetReynolds() << ", computed using initial values."<< "\n";
7314  Breakdown_file << "Reynolds number is a byproduct of inputs only (not used internally)." << "\n";
7315  }
7316  Breakdown_file << "SI units only. The grid should be dimensional (meters)." << "\n";
7317 
7318  switch (config[val_iZone]->GetKind_DensityModel()) {
7319 
7320  case CONSTANT:
7321  if (energy) Breakdown_file << "Energy equation is active and decoupled." << "\n";
7322  else Breakdown_file << "No energy equation." << "\n";
7323  break;
7324 
7325  case BOUSSINESQ:
7326  if (energy) Breakdown_file << "Energy equation is active and coupled through Boussinesq approx." << "\n";
7327  break;
7328 
7329  case VARIABLE:
7330  if (energy) Breakdown_file << "Energy equation is active and coupled for variable density." << "\n";
7331  break;
7332 
7333  }
7334 
7335  Breakdown_file <<"-- Input conditions:"<< "\n";
7336 
7337  switch (config[val_iZone]->GetKind_FluidModel()) {
7338 
7339  case CONSTANT_DENSITY:
7340  Breakdown_file << "Fluid Model: CONSTANT_DENSITY "<< "\n";
7341  if (energy) {
7342  Breakdown_file << "Specific heat at constant pressure (Cp): " << config[val_iZone]->GetSpecific_Heat_Cp() << " N.m/kg.K." << "\n";
7343  }
7344  if (boussinesq) Breakdown_file << "Thermal expansion coefficient: " << config[val_iZone]->GetThermal_Expansion_Coeff() << " K^-1." << "\n";
7345  Breakdown_file << "Thermodynamic pressure not required." << "\n";
7346  break;
7347 
7348  case INC_IDEAL_GAS:
7349  Breakdown_file << "Fluid Model: INC_IDEAL_GAS "<< endl;
7350  Breakdown_file << "Variable density incompressible flow using ideal gas law." << endl;
7351  Breakdown_file << "Density is a function of temperature (constant thermodynamic pressure)." << endl;
7352  Breakdown_file << "Specific heat at constant pressure (Cp): " << config[val_iZone]->GetSpecific_Heat_Cp() << " N.m/kg.K." << endl;
7353  Breakdown_file << "Molecular weight : "<< config[val_iZone]->GetMolecular_Weight() << " g/mol" << endl;
7354  Breakdown_file << "Specific gas constant: " << config[val_iZone]->GetGas_Constant() << " N.m/kg.K." << endl;
7355  Breakdown_file << "Thermodynamic pressure: " << config[val_iZone]->GetPressure_Thermodynamic();
7356  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << endl;
7357  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << endl;
7358  break;
7359 
7360  }
7361  if (viscous) {
7362  switch (config[val_iZone]->GetKind_ViscosityModel()) {
7363 
7364  case CONSTANT_VISCOSITY:
7365  Breakdown_file << "Viscosity Model: CONSTANT_VISCOSITY "<< "\n";
7366  Breakdown_file << "Constant Laminar Viscosity: " << config[val_iZone]->GetMu_Constant();
7367  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n";
7368  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n";
7369  Breakdown_file << "Laminar Viscosity (non-dim): " << config[val_iZone]->GetMu_ConstantND()<< "\n";
7370  break;
7371 
7372  case SUTHERLAND:
7373  Breakdown_file << "Viscosity Model: SUTHERLAND "<< "\n";
7374  Breakdown_file << "Ref. Laminar Viscosity: " << config[val_iZone]->GetMu_Ref();
7375  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n";
7376  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n";
7377  Breakdown_file << "Ref. Temperature: " << config[val_iZone]->GetMu_Temperature_Ref();
7378  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
7379  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
7380  Breakdown_file << "Sutherland Constant: "<< config[val_iZone]->GetMu_S();
7381  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
7382  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
7383  Breakdown_file << "Laminar Viscosity (non-dim): " << config[val_iZone]->GetMu_ConstantND()<< "\n";
7384  Breakdown_file << "Ref. Temperature (non-dim): " << config[val_iZone]->GetMu_Temperature_RefND()<< "\n";
7385  Breakdown_file << "Sutherland constant (non-dim): "<< config[val_iZone]->GetMu_SND()<< "\n";
7386  break;
7387 
7388  }
7389 
7390  if (energy) {
7391  switch (config[val_iZone]->GetKind_ConductivityModel()) {
7392 
7393  case CONSTANT_PRANDTL:
7394  Breakdown_file << "Conductivity Model: CONSTANT_PRANDTL "<< "\n";
7395  Breakdown_file << "Prandtl (Laminar): " << config[val_iZone]->GetPrandtl_Lam()<< "\n";
7396  Breakdown_file << "Prandtl (Turbulent): " << config[val_iZone]->GetPrandtl_Turb()<< "\n";
7397  break;
7398 
7399  case CONSTANT_CONDUCTIVITY:
7400  Breakdown_file << "Conductivity Model: CONSTANT_CONDUCTIVITY "<< "\n";
7401  Breakdown_file << "Molecular Conductivity: " << config[val_iZone]->GetKt_Constant()<< " W/m^2.K." << "\n";
7402  Breakdown_file << "Molecular Conductivity (non-dim): " << config[val_iZone]->GetKt_ConstantND()<< "\n";
7403  break;
7404 
7405  }
7406  }
7407 
7408  }
7409 
7410  if (config[val_iZone]->GetKind_FluidModel() == CONSTANT_DENSITY) {
7411  Breakdown_file << "Bulk modulus: " << config[val_iZone]->GetBulk_Modulus();
7412  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
7413  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
7414  }
7415 
7416  Breakdown_file << "Initial dynamic pressure: " << config[val_iZone]->GetPressure_FreeStream();
7417  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
7418  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
7419 
7420  Breakdown_file << "Initial total pressure: " << config[val_iZone]->GetPressure_FreeStream() + 0.5*config[val_iZone]->GetDensity_FreeStream()*config[val_iZone]->GetModVel_FreeStream()*config[val_iZone]->GetModVel_FreeStream();
7421  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
7422  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
7423 
7424  if (energy) {
7425  Breakdown_file << "Initial temperature: " << config[val_iZone]->GetTemperature_FreeStream();
7426  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
7427  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
7428  }
7429 
7430  Breakdown_file << "Initial density: " << config[val_iZone]->GetDensity_FreeStream();
7431  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " kg/m^3." << "\n";
7432  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " slug/ft^3." << "\n";
7433 
7434  if (nDim == 2) {
7435  Breakdown_file << "Initial velocity: (" << config[val_iZone]->GetVelocity_FreeStream()[0] << ", ";
7436  Breakdown_file << config[val_iZone]->GetVelocity_FreeStream()[1] << ")";
7437  }
7438  if (nDim == 3) {
7439  Breakdown_file << "Initial velocity: (" << config[val_iZone]->GetVelocity_FreeStream()[0] << ", ";
7440  Breakdown_file << config[val_iZone]->GetVelocity_FreeStream()[1] << ", " << config[val_iZone]->GetVelocity_FreeStream()[2] << ")";
7441  }
7442  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m/s. ";
7443  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft/s. ";
7444 
7445  Breakdown_file << "Magnitude: " << config[val_iZone]->GetModVel_FreeStream();
7446  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m/s." << "\n";
7447  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft/s." << "\n";
7448 
7449  if (viscous) {
7450  Breakdown_file << "Initial laminar viscosity: " << config[val_iZone]->GetViscosity_FreeStream();
7451  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n";
7452  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n";
7453  if (turbulent) {
7454  Breakdown_file << "Initial turb. kinetic energy per unit mass: " << config[val_iZone]->GetTke_FreeStream();
7455  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m^2/s^2." << "\n";
7456  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft^2/s^2." << "\n";
7457  Breakdown_file << "Initial specific dissipation: " << config[val_iZone]->GetOmega_FreeStream();
7458  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " 1/s." << "\n";
7459  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " 1/s." << "\n";
7460  }
7461  }
7462 
7463  if (unsteady) { Breakdown_file << "Total time: " << config[val_iZone]->GetTotal_UnstTime() << " s. Time step: " << config[val_iZone]->GetDelta_UnstTime() << " s." << "\n"; }
7464 
7465  /*--- Print out reference values. ---*/
7466 
7467  Breakdown_file <<"-- Reference values:"<< "\n";
7468 
7469  if (config[val_iZone]->GetKind_FluidModel() != CONSTANT_DENSITY) {
7470  Breakdown_file << "Reference specific gas constant: " << config[val_iZone]->GetGas_Constant_Ref();
7471  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.m/kg.K." << "\n";
7472  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.ft/slug.R." << "\n";
7473  } else {
7474  if (energy) {
7475  Breakdown_file << "Reference specific heat: " << config[val_iZone]->GetGas_Constant_Ref();
7476  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.m/kg.K." << "\n";
7477  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.ft/slug.R." << "\n";
7478  }
7479  }
7480 
7481  Breakdown_file << "Reference pressure: " << config[val_iZone]->GetPressure_Ref();
7482  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n";
7483  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n";
7484 
7485  if (energy) {
7486  Breakdown_file << "Reference temperature: " << config[val_iZone]->GetTemperature_Ref();
7487  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n";
7488  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n";
7489  }
7490 
7491  Breakdown_file << "Reference density: " << config[val_iZone]->GetDensity_Ref();
7492  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " kg/m^3." << "\n";
7493  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " slug/ft^3." << "\n";
7494 
7495  Breakdown_file << "Reference velocity: " << config[val_iZone]->GetVelocity_Ref();
7496  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m/s." << "\n";
7497  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft/s." << "\n";
7498 
7499  Breakdown_file << "Reference length: " << config[val_iZone]->GetLength_Ref();
7500  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m." << "\n";
7501  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " in." << "\n";
7502 
7503  if (viscous) {
7504  Breakdown_file << "Reference viscosity: " << config[val_iZone]->GetViscosity_Ref();
7505  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n";
7506  else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n";
7507  }
7508 
7509  if (unsteady) Breakdown_file << "Reference time: " << config[val_iZone]->GetTime_Ref() <<" s." << "\n";
7510 
7511  /*--- Print out resulting non-dim values here. ---*/
7512 
7513  Breakdown_file << "-- Resulting non-dimensional state:" << "\n";
7514  Breakdown_file << "Mach number (non-dim): " << config[val_iZone]->GetMach() << "\n";
7515  if (viscous) {
7516  Breakdown_file << "Reynolds number (per m): " << config[val_iZone]->GetReynolds() << "\n";
7517  }
7518 
7519  if (config[val_iZone]->GetKind_FluidModel() != CONSTANT_DENSITY) {
7520  Breakdown_file << "Specific gas constant (non-dim): " << config[val_iZone]->GetGas_ConstantND() << "\n";
7521  Breakdown_file << "Initial thermodynamic pressure (non-dim): " << config[val_iZone]->GetPressure_ThermodynamicND() << "\n";
7522  } else {
7523  if (energy) {
7524  Breakdown_file << "Specific heat at constant pressure (non-dim): " << config[val_iZone]->GetSpecific_Heat_CpND() << "\n";
7525  if (boussinesq) Breakdown_file << "Thermal expansion coefficient (non-dim.): " << config[val_iZone]->GetThermal_Expansion_CoeffND() << " K^-1." << "\n";
7526  }
7527  }
7528 
7529  if (energy) Breakdown_file << "Initial temperature (non-dim): " << config[val_iZone]->GetTemperature_FreeStreamND() << "\n";
7530  Breakdown_file << "Initial pressure (non-dim): " << config[val_iZone]->GetPressure_FreeStreamND() << "\n";
7531  Breakdown_file << "Initial density (non-dim): " << config[val_iZone]->GetDensity_FreeStreamND() << "\n";
7532 
7533  if (nDim == 2) {
7534  Breakdown_file << "Initial velocity (non-dim): (" << config[val_iZone]->GetVelocity_FreeStreamND()[0] << ", ";
7535  Breakdown_file << config[val_iZone]->GetVelocity_FreeStreamND()[1] << "). ";
7536  } else {
7537  Breakdown_file << "Initial velocity (non-dim): (" << config[val_iZone]->GetVelocity_FreeStreamND()[0] << ", ";
7538  Breakdown_file << config[val_iZone]->GetVelocity_FreeStreamND()[1] << ", " << config[val_iZone]->GetVelocity_FreeStreamND()[2] << "). ";
7539  }
7540  Breakdown_file << "Magnitude: " << config[val_iZone]->GetModVel_FreeStreamND() << "\n";
7541 
7542  if (viscous) {
7543  Breakdown_file << "Initial viscosity (non-dim): " << config[val_iZone]->GetViscosity_FreeStreamND() << "\n";
7544  if (turbulent) {
7545  Breakdown_file << "Initial turb. kinetic energy (non-dim): " << config[val_iZone]->GetTke_FreeStreamND() << "\n";
7546  Breakdown_file << "Initial specific dissipation (non-dim): " << config[val_iZone]->GetOmega_FreeStreamND() << "\n";
7547  }
7548  }
7549 
7550  if (unsteady) {
7551  Breakdown_file << "Total time (non-dim): " << config[val_iZone]->GetTotal_UnstTimeND() << "\n";
7552  Breakdown_file << "Time step (non-dim): " << config[val_iZone]->GetDelta_UnstTimeND() << "\n";
7553  }
7554 
7555  }
7556 
7557  /*--- Begin forces breakdown info. ---*/
7558 
7559  Breakdown_file << fixed;
7560  Breakdown_file << "\n" << "\n" <<"Forces breakdown:" << "\n" << "\n";
7561 
7562  if (nDim == 3) {
7563  su2double m = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFz()/solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFx();
7564  su2double term = (Total_CoPz/m)-Total_CoPx;
7565 
7566  if (term > 0) Breakdown_file << "Center of Pressure: X=" << 1/m <<"Z-"<< term << "." << "\n\n";
7567  else Breakdown_file << "Center of Pressure: X=" << 1/m <<"Z+"<< fabs(term);
7568  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m." << "\n\n";
7569  else Breakdown_file << " in." << "\n\n";
7570  }
7571  else {
7572  su2double m = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFy()/solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFx();
7573  su2double term = (Total_CoPy/m)-Total_CoPx;
7574  if (term > 0) Breakdown_file << "Center of Pressure: X=" << 1/m <<"Y-"<< term << "." << "\n\n";
7575  else Breakdown_file << "Center of Pressure: X=" << 1/m <<"Y+"<< fabs(term);
7576  if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m." << "\n\n";
7577  else Breakdown_file << " in." << "\n\n";
7578  }
7579 
7580  /*--- Reference area and force factors. ---*/
7581 
7582  su2double RefDensity, RefArea, RefVel, Factor, Ref;
7583  RefArea = config[val_iZone]->GetRefArea();
7584  if (compressible) {
7585  RefDensity = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetDensity_Inf();
7586  RefVel = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetModVelocity_Inf();
7587  } else {
7588  if ((config[val_iZone]->GetRef_Inc_NonDim() == DIMENSIONAL) ||
7589  (config[val_iZone]->GetRef_Inc_NonDim() == INITIAL_VALUES)) {
7590  RefDensity = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetDensity_Inf();
7591  RefVel = 0.0;
7592  for (iDim = 0; iDim < nDim; iDim++)
7593  RefVel += solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetVelocity_Inf(iDim)*solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetVelocity_Inf(iDim);
7594  RefVel = sqrt(RefVel);
7595  } else {
7596  RefDensity = config[val_iZone]->GetInc_Density_Ref();
7597  RefVel = config[val_iZone]->GetInc_Velocity_Ref();
7598  }
7599  }
7600  Factor = (0.5*RefDensity*RefArea*RefVel*RefVel);
7601  Ref = config[val_iZone]->GetDensity_Ref() * config[val_iZone]->GetVelocity_Ref() * config[val_iZone]->GetVelocity_Ref() * 1.0 * 1.0;
7602 
7603  Breakdown_file << "NOTE: Multiply forces by the non-dimensional factor: " << Factor << ", and the reference factor: " << Ref << "\n";
7604  Breakdown_file << "to obtain the dimensional force." << "\n" << "\n";
7605 
7606  Breakdown_file << "Total CL: ";
7607  Breakdown_file.precision(15);
7608  Breakdown_file.width(18);
7609  Breakdown_file << Total_CL;
7610  Breakdown_file << " | Pressure (";
7611  Breakdown_file.width(5);
7612  Breakdown_file << SU2_TYPE::Int((Inv_CL * 100.0) / (Total_CL + EPS));
7613  Breakdown_file << "%): ";
7614  Breakdown_file.width(18);
7615  Breakdown_file << Inv_CL;
7616  Breakdown_file << " | Friction (";
7617  Breakdown_file.width(5);
7618  Breakdown_file << SU2_TYPE::Int((Visc_CL * 100.0) / (Total_CL + EPS));
7619  Breakdown_file << "%): ";
7620  Breakdown_file.width(18);
7621  Breakdown_file << Visc_CL;
7622  Breakdown_file << " | Momentum (";
7623  Breakdown_file.width(5);
7624  Breakdown_file << SU2_TYPE::Int((Mnt_CL * 100.0) / (Total_CL + EPS));
7625  Breakdown_file << "%): ";
7626  Breakdown_file.width(18);
7627  Breakdown_file << Mnt_CL << "\n";
7628 
7629  Breakdown_file << "Total CD: ";
7630  Breakdown_file.width(18);
7631  Breakdown_file << Total_CD;
7632  Breakdown_file << " | Pressure (";
7633  Breakdown_file.width(5);
7634  Breakdown_file << SU2_TYPE::Int((Inv_CD * 100.0) / (Total_CD + EPS)) << "%): ";
7635  Breakdown_file.width(18);
7636  Breakdown_file << Inv_CD;
7637  Breakdown_file << " | Friction (";
7638  Breakdown_file.width(5);
7639  Breakdown_file << SU2_TYPE::Int((Visc_CD * 100.0) / (Total_CD + EPS)) << "%): ";
7640  Breakdown_file.width(18);
7641  Breakdown_file << Visc_CD;
7642  Breakdown_file << " | Momentum (";
7643  Breakdown_file.width(5);
7644  Breakdown_file << SU2_TYPE::Int((Mnt_CD * 100.0) / (Total_CD + EPS)) << "%): ";
7645  Breakdown_file.width(18);
7646  Breakdown_file << Mnt_CD << "\n";
7647 
7648  if (nDim == 3) {
7649  Breakdown_file << "Total CSF: ";
7650  Breakdown_file.width(18);
7651  Breakdown_file << Total_CSF;
7652  Breakdown_file << " | Pressure (";
7653  Breakdown_file.width(5);
7654  Breakdown_file << SU2_TYPE::Int((Inv_CSF * 100.0) / (Total_CSF + EPS));
7655  Breakdown_file << "%): ";
7656  Breakdown_file.width(18);
7657  Breakdown_file << Inv_CSF;
7658  Breakdown_file << " | Friction (";
7659  Breakdown_file.width(5);
7660  Breakdown_file << SU2_TYPE::Int((Visc_CSF * 100.0) / (Total_CSF + EPS));
7661  Breakdown_file << "%): ";
7662  Breakdown_file.width(18);
7663  Breakdown_file << Visc_CSF;
7664  Breakdown_file << " | Momentum (";
7665  Breakdown_file.width(5);
7666  Breakdown_file << SU2_TYPE::Int((Mnt_CSF * 100.0) / (Total_CSF + EPS));
7667  Breakdown_file << "%): ";
7668  Breakdown_file.width(18);
7669  Breakdown_file << Mnt_CSF << "\n";
7670  }
7671 
7672  Breakdown_file << "Total CL/CD: ";
7673  Breakdown_file.width(18);
7674  Breakdown_file << Total_CEff;
7675  Breakdown_file << " | Pressure (";
7676  Breakdown_file.width(5);
7677  Breakdown_file << SU2_TYPE::Int((Inv_CEff * 100.0) / (Total_CEff + EPS));
7678  Breakdown_file << "%): ";
7679  Breakdown_file.width(18);
7680  Breakdown_file << Inv_CEff;
7681  Breakdown_file << " | Friction (";
7682  Breakdown_file.width(5);
7683  Breakdown_file << SU2_TYPE::Int((Visc_CEff * 100.0) / (Total_CEff + EPS));
7684  Breakdown_file << "%): ";
7685  Breakdown_file.width(18);
7686  Breakdown_file << Visc_CEff;
7687  Breakdown_file << " | Momentum (";
7688  Breakdown_file.width(5);
7689  Breakdown_file << SU2_TYPE::Int((Mnt_CEff * 100.0) / (Total_CEff + EPS));
7690  Breakdown_file << "%): ";
7691  Breakdown_file.width(18);
7692  Breakdown_file << Mnt_CEff << "\n";
7693 
7694  if (nDim == 3) {
7695  Breakdown_file << "Total CMx: ";
7696  Breakdown_file.width(18);
7697  Breakdown_file << Total_CMx;
7698  Breakdown_file << " | Pressure (";
7699  Breakdown_file.width(5);
7700  Breakdown_file << SU2_TYPE::Int((Inv_CMx * 100.0) / (Total_CMx + EPS));
7701  Breakdown_file << "%): ";
7702  Breakdown_file.width(18);
7703  Breakdown_file << Inv_CMx;
7704  Breakdown_file << " | Friction (";
7705  Breakdown_file.width(5);
7706  Breakdown_file << SU2_TYPE::Int((Visc_CMx * 100.0) / (Total_CMx + EPS));
7707  Breakdown_file << "%): ";
7708  Breakdown_file.width(18);
7709  Breakdown_file << Visc_CMx;
7710  Breakdown_file << " | Momentum (";
7711  Breakdown_file.width(5);
7712  Breakdown_file << SU2_TYPE::Int((Mnt_CMx * 100.0) / (Total_CMx + EPS));
7713  Breakdown_file << "%): ";
7714  Breakdown_file.width(18);
7715  Breakdown_file << Mnt_CMx << "\n";
7716 
7717  Breakdown_file << "Total CMy: ";
7718  Breakdown_file.width(18);
7719  Breakdown_file << Total_CMy;
7720  Breakdown_file << " | Pressure (";
7721  Breakdown_file.width(5);
7722  Breakdown_file << SU2_TYPE::Int((Inv_CMy * 100.0) / (Total_CMy + EPS));
7723  Breakdown_file << "%): ";
7724  Breakdown_file.width(18);
7725  Breakdown_file << Inv_CMy;
7726  Breakdown_file << " | Friction (";
7727  Breakdown_file.width(5);
7728  Breakdown_file << SU2_TYPE::Int((Visc_CMy * 100.0) / (Total_CMy + EPS));
7729  Breakdown_file << "%): ";
7730  Breakdown_file.width(18);
7731  Breakdown_file << Visc_CMy;
7732  Breakdown_file << " | Momentum (";
7733  Breakdown_file.width(5);
7734  Breakdown_file << SU2_TYPE::Int((Mnt_CMz * 100.0) / (Total_CMz + EPS));
7735  Breakdown_file << "%): ";
7736  Breakdown_file.width(18);
7737  Breakdown_file << Mnt_CMy << "\n";
7738  }
7739 
7740  Breakdown_file << "Total CMz: ";
7741  Breakdown_file.width(18);
7742  Breakdown_file << Total_CMz;
7743  Breakdown_file << " | Pressure (";
7744  Breakdown_file.width(5);
7745  Breakdown_file << SU2_TYPE::Int((Inv_CMz * 100.0) / (Total_CMz + EPS));
7746  Breakdown_file << "%): ";
7747  Breakdown_file.width(18);
7748  Breakdown_file << Inv_CMz;
7749  Breakdown_file << " | Friction (";
7750  Breakdown_file.width(5);
7751  Breakdown_file << SU2_TYPE::Int((Visc_CMz * 100.0) / (Total_CMz + EPS));
7752  Breakdown_file << "%): ";
7753  Breakdown_file.width(18);
7754  Breakdown_file << Visc_CMz;
7755  Breakdown_file << " | Momentum (";
7756  Breakdown_file.width(5);
7757  Breakdown_file << SU2_TYPE::Int((Mnt_CMz * 100.0) / (Total_CMz + EPS));
7758  Breakdown_file << "%): ";
7759  Breakdown_file.width(18);
7760  Breakdown_file << Mnt_CMz << "\n";
7761 
7762  Breakdown_file << "Total CFx: ";
7763  Breakdown_file.width(18);
7764  Breakdown_file << Total_CFx;
7765  Breakdown_file << " | Pressure (";
7766  Breakdown_file.width(5);
7767  Breakdown_file << SU2_TYPE::Int((Inv_CFx * 100.0) / (Total_CFx + EPS));
7768  Breakdown_file << "%): ";
7769  Breakdown_file.width(18);
7770  Breakdown_file << Inv_CFx;
7771  Breakdown_file << " | Friction (";
7772  Breakdown_file.width(5);
7773  Breakdown_file << SU2_TYPE::Int((Visc_CFx * 100.0) / (Total_CFx + EPS));
7774  Breakdown_file << "%): ";
7775  Breakdown_file.width(18);
7776  Breakdown_file << Visc_CFx;
7777  Breakdown_file << " | Momentum (";
7778  Breakdown_file.width(5);
7779  Breakdown_file << SU2_TYPE::Int((Mnt_CFx * 100.0) / (Total_CFx + EPS));
7780  Breakdown_file << "%): ";
7781  Breakdown_file.width(18);
7782  Breakdown_file << Mnt_CFx << "\n";
7783 
7784  Breakdown_file << "Total CFy: ";
7785  Breakdown_file.width(18);
7786  Breakdown_file << Total_CFy;
7787  Breakdown_file << " | Pressure (";
7788  Breakdown_file.width(5);
7789  Breakdown_file << SU2_TYPE::Int((Inv_CFy * 100.0) / (Total_CFy + EPS));
7790  Breakdown_file << "%): ";
7791  Breakdown_file.width(18);
7792  Breakdown_file << Inv_CFy;
7793  Breakdown_file << " | Friction (";
7794  Breakdown_file.width(5);
7795  Breakdown_file << SU2_TYPE::Int((Visc_CFy * 100.0) / (Total_CFy + EPS));
7796  Breakdown_file << "%): ";
7797  Breakdown_file.width(18);
7798  Breakdown_file << Visc_CFy;
7799  Breakdown_file << " | Momentum (";
7800  Breakdown_file.width(5);
7801  Breakdown_file << SU2_TYPE::Int((Mnt_CFy * 100.0) / (Total_CFy + EPS));
7802  Breakdown_file << "%): ";
7803  Breakdown_file.width(18);
7804  Breakdown_file << Mnt_CFy << "\n";
7805 
7806  if (nDim == 3) {
7807  Breakdown_file << "Total CFz: ";
7808  Breakdown_file.width(18);
7809  Breakdown_file << Total_CFz;
7810  Breakdown_file << " | Pressure (";
7811  Breakdown_file.width(5);
7812  Breakdown_file << SU2_TYPE::Int((Inv_CFz * 100.0) / (Total_CFz + EPS));
7813  Breakdown_file << "%): ";
7814  Breakdown_file.width(18);
7815  Breakdown_file << Inv_CFz;
7816  Breakdown_file << " | Friction (";
7817  Breakdown_file.width(5);
7818  Breakdown_file << SU2_TYPE::Int((Visc_CFz * 100.0) / (Total_CFz + EPS));
7819  Breakdown_file << "%): ";
7820  Breakdown_file.width(18);
7821  Breakdown_file << Visc_CFz;
7822  Breakdown_file << " | Momentum (";
7823  Breakdown_file.width(5);
7824  Breakdown_file << SU2_TYPE::Int((Mnt_CFz * 100.0) / (Total_CFz + EPS));
7825  Breakdown_file << "%): ";
7826  Breakdown_file.width(18);
7827  Breakdown_file << Mnt_CFz << "\n";
7828  }
7829 
7830  Breakdown_file << "\n" << "\n";
7831 
7832  for (iMarker_Monitoring = 0;
7833  iMarker_Monitoring < config[val_iZone]->GetnMarker_Monitoring();
7834  iMarker_Monitoring++) {
7835 
7836  Breakdown_file << "Surface name: "
7837  << config[val_iZone]->GetMarker_Monitoring_TagBound(
7838  iMarker_Monitoring) << "\n" << "\n";
7839 
7840  Breakdown_file << "Total CL (";
7841  Breakdown_file.width(5);
7842  Breakdown_file
7843  << SU2_TYPE::Int(
7844  (Surface_CL[iMarker_Monitoring] * 100.0)
7845  / (Total_CL + EPS));
7846  Breakdown_file << "%): ";
7847  Breakdown_file.width(18);
7848  Breakdown_file << Surface_CL[iMarker_Monitoring];
7849  Breakdown_file << " | Pressure (";
7850  Breakdown_file.width(5);
7851  Breakdown_file
7852  << SU2_TYPE::Int(
7853  (Surface_CL_Inv[iMarker_Monitoring] * 100.0)
7854  / (Surface_CL[iMarker_Monitoring] + EPS));
7855  Breakdown_file << "%): ";
7856  Breakdown_file.width(18);
7857  Breakdown_file << Surface_CL_Inv[iMarker_Monitoring];
7858  Breakdown_file << " | Friction (";
7859  Breakdown_file.width(5);
7860  Breakdown_file
7861  << SU2_TYPE::Int(
7862  (Surface_CL_Visc[iMarker_Monitoring] * 100.0)
7863  / (Surface_CL[iMarker_Monitoring] + EPS));
7864  Breakdown_file << "%): ";
7865  Breakdown_file.width(18);
7866  Breakdown_file << Surface_CL_Visc[iMarker_Monitoring];
7867  Breakdown_file << " | Momentum (";
7868  Breakdown_file.width(5);
7869  Breakdown_file
7870  << SU2_TYPE::Int(
7871  (Surface_CL_Mnt[iMarker_Monitoring] * 100.0)
7872  / (Surface_CL[iMarker_Monitoring] + EPS));
7873  Breakdown_file << "%): ";
7874  Breakdown_file.width(18);
7875  Breakdown_file << Surface_CL_Mnt[iMarker_Monitoring] << "\n";
7876 
7877  Breakdown_file << "Total CD (";
7878  Breakdown_file.width(5);
7879  Breakdown_file
7880  << SU2_TYPE::Int(
7881  (Surface_CD[iMarker_Monitoring] * 100.0)
7882  / (Total_CD + EPS));
7883  Breakdown_file << "%): ";
7884  Breakdown_file.width(18);
7885  Breakdown_file << Surface_CD[iMarker_Monitoring];
7886  Breakdown_file << " | Pressure (";
7887  Breakdown_file.width(5);
7888  Breakdown_file
7889  << SU2_TYPE::Int(
7890  (Surface_CD_Inv[iMarker_Monitoring] * 100.0)
7891  / (Surface_CD[iMarker_Monitoring] + EPS));
7892  Breakdown_file << "%): ";
7893  Breakdown_file.width(18);
7894  Breakdown_file << Surface_CD_Inv[iMarker_Monitoring];
7895  Breakdown_file << " | Friction (";
7896  Breakdown_file.width(5);
7897  Breakdown_file
7898  << SU2_TYPE::Int(
7899  (Surface_CD_Visc[iMarker_Monitoring] * 100.0)
7900  / (Surface_CD[iMarker_Monitoring] + EPS));
7901  Breakdown_file << "%): ";
7902  Breakdown_file.width(18);
7903  Breakdown_file << Surface_CD_Visc[iMarker_Monitoring];
7904  Breakdown_file << " | Momentum (";
7905  Breakdown_file.width(5);
7906  Breakdown_file
7907  << SU2_TYPE::Int(
7908  (Surface_CD_Mnt[iMarker_Monitoring] * 100.0)
7909  / (Surface_CD[iMarker_Monitoring] + EPS));
7910  Breakdown_file << "%): ";
7911  Breakdown_file.width(18);
7912  Breakdown_file << Surface_CD_Mnt[iMarker_Monitoring] << "\n";
7913 
7914  if (nDim == 3) {
7915  Breakdown_file << "Total CSF (";
7916  Breakdown_file.width(5);
7917  Breakdown_file
7918  << SU2_TYPE::Int(
7919  (Surface_CSF[iMarker_Monitoring] * 100.0)
7920  / (Total_CSF + EPS));
7921  Breakdown_file << "%): ";
7922  Breakdown_file.width(18);
7923  Breakdown_file << Surface_CSF[iMarker_Monitoring];
7924  Breakdown_file << " | Pressure (";
7925  Breakdown_file.width(5);
7926  Breakdown_file
7927  << SU2_TYPE::Int(
7928  (Surface_CSF_Inv[iMarker_Monitoring] * 100.0)
7929  / (Surface_CSF[iMarker_Monitoring] + EPS));
7930  Breakdown_file << "%): ";
7931  Breakdown_file.width(18);
7932  Breakdown_file << Surface_CSF_Inv[iMarker_Monitoring];
7933  Breakdown_file << " | Friction (";
7934  Breakdown_file.width(5);
7935  Breakdown_file
7936  << SU2_TYPE::Int(
7937  (Surface_CSF_Visc[iMarker_Monitoring] * 100.0)
7938  / (Surface_CSF[iMarker_Monitoring] + EPS));
7939  Breakdown_file << "%): ";
7940  Breakdown_file.width(18);
7941  Breakdown_file
7942  << Surface_CSF_Visc[iMarker_Monitoring];
7943  Breakdown_file << " | Momentum (";
7944  Breakdown_file.width(5);
7945  Breakdown_file
7946  << SU2_TYPE::Int(
7947  (Surface_CSF_Mnt[iMarker_Monitoring] * 100.0)
7948  / (Surface_CSF[iMarker_Monitoring] + EPS));
7949  Breakdown_file << "%): ";
7950  Breakdown_file.width(18);
7951  Breakdown_file
7952  << Surface_CSF_Mnt[iMarker_Monitoring] << "\n";
7953  }
7954 
7955  Breakdown_file << "Total CL/CD (";
7956  Breakdown_file.width(5);
7957  Breakdown_file
7958  << SU2_TYPE::Int(
7959  (Surface_CEff[iMarker_Monitoring] * 100.0) / (Total_CEff + EPS));
7960  Breakdown_file << "%): ";
7961  Breakdown_file.width(18);
7962  Breakdown_file << Surface_CEff[iMarker_Monitoring];
7963  Breakdown_file << " | Pressure (";
7964  Breakdown_file.width(5);
7965  Breakdown_file
7966  << SU2_TYPE::Int(
7967  (Surface_CEff_Inv[iMarker_Monitoring] * 100.0)
7968  / (Surface_CEff[iMarker_Monitoring] + EPS));
7969  Breakdown_file << "%): ";
7970  Breakdown_file.width(18);
7971  Breakdown_file << Surface_CEff_Inv[iMarker_Monitoring];
7972  Breakdown_file << " | Friction (";
7973  Breakdown_file.width(5);
7974  Breakdown_file
7975  << SU2_TYPE::Int(
7976  (Surface_CEff_Visc[iMarker_Monitoring] * 100.0)
7977  / (Surface_CEff[iMarker_Monitoring] + EPS));
7978  Breakdown_file << "%): ";
7979  Breakdown_file.width(18);
7980  Breakdown_file
7981  << Surface_CEff_Visc[iMarker_Monitoring];
7982  Breakdown_file << " | Momentum (";
7983  Breakdown_file.width(5);
7984  Breakdown_file
7985  << SU2_TYPE::Int(
7986  (Surface_CEff_Mnt[iMarker_Monitoring] * 100.0)
7987  / (Surface_CEff[iMarker_Monitoring] + EPS));
7988  Breakdown_file << "%): ";
7989  Breakdown_file.width(18);
7990  Breakdown_file
7991  << Surface_CEff_Mnt[iMarker_Monitoring] << "\n";
7992 
7993  if (nDim == 3) {
7994 
7995  Breakdown_file << "Total CMx (";
7996  Breakdown_file.width(5);
7997  Breakdown_file
7998  << SU2_TYPE::Int(
7999  (Surface_CMx[iMarker_Monitoring] * 100.0) / (Total_CMx + EPS));
8000  Breakdown_file << "%): ";
8001  Breakdown_file.width(18);
8002  Breakdown_file << Surface_CMx[iMarker_Monitoring];
8003  Breakdown_file << " | Pressure (";
8004  Breakdown_file.width(5);
8005  Breakdown_file
8006  << SU2_TYPE::Int(
8007  (Surface_CMx_Inv[iMarker_Monitoring] * 100.0)
8008  / (Surface_CMx[iMarker_Monitoring] + EPS));
8009  Breakdown_file << "%): ";
8010  Breakdown_file.width(18);
8011  Breakdown_file << Surface_CMx_Inv[iMarker_Monitoring];
8012  Breakdown_file << " | Friction (";
8013  Breakdown_file.width(5);
8014  Breakdown_file
8015  << SU2_TYPE::Int(
8016  (Surface_CMx_Visc[iMarker_Monitoring] * 100.0)
8017  / (Surface_CMx[iMarker_Monitoring] + EPS));
8018  Breakdown_file << "%): ";
8019  Breakdown_file.width(18);
8020  Breakdown_file
8021  << Surface_CMx_Visc[iMarker_Monitoring];
8022  Breakdown_file << " | Momentum (";
8023  Breakdown_file.width(5);
8024  Breakdown_file
8025  << SU2_TYPE::Int(
8026  (Surface_CMx_Mnt[iMarker_Monitoring] * 100.0)
8027  / (Surface_CMx[iMarker_Monitoring] + EPS));
8028  Breakdown_file << "%): ";
8029  Breakdown_file.width(18);
8030  Breakdown_file
8031  << Surface_CMx_Mnt[iMarker_Monitoring] << "\n";
8032 
8033  Breakdown_file << "Total CMy (";
8034  Breakdown_file.width(5);
8035  Breakdown_file
8036  << SU2_TYPE::Int(
8037  (Surface_CMy[iMarker_Monitoring] * 100.0) / (Total_CMy + EPS));
8038  Breakdown_file << "%): ";
8039  Breakdown_file.width(18);
8040  Breakdown_file << Surface_CMy[iMarker_Monitoring];
8041  Breakdown_file << " | Pressure (";
8042  Breakdown_file.width(5);
8043  Breakdown_file
8044  << SU2_TYPE::Int(
8045  (Surface_CMy_Inv[iMarker_Monitoring] * 100.0)
8046  / (Surface_CMy[iMarker_Monitoring] + EPS));
8047  Breakdown_file << "%): ";
8048  Breakdown_file.width(18);
8049  Breakdown_file << Surface_CMy_Inv[iMarker_Monitoring];
8050  Breakdown_file << " | Friction (";
8051  Breakdown_file.width(5);
8052  Breakdown_file
8053  << SU2_TYPE::Int(
8054  (Surface_CMy_Visc[iMarker_Monitoring] * 100.0)
8055  / (Surface_CMy[iMarker_Monitoring] + EPS));
8056  Breakdown_file << "%): ";
8057  Breakdown_file.width(18);
8058  Breakdown_file
8059  << Surface_CMy_Visc[iMarker_Monitoring];
8060  Breakdown_file << " | Momentum (";
8061  Breakdown_file.width(5);
8062  Breakdown_file
8063  << SU2_TYPE::Int(
8064  (Surface_CMy_Mnt[iMarker_Monitoring] * 100.0)
8065  / (Surface_CMy[iMarker_Monitoring] + EPS));
8066  Breakdown_file << "%): ";
8067  Breakdown_file.width(18);
8068  Breakdown_file
8069  << Surface_CMy_Mnt[iMarker_Monitoring] << "\n";
8070  }
8071 
8072  Breakdown_file << "Total CMz (";
8073  Breakdown_file.width(5);
8074  Breakdown_file
8075  << SU2_TYPE::Int((Surface_CMz[iMarker_Monitoring] * 100.0) / (Total_CMz + EPS));
8076  Breakdown_file << "%): ";
8077  Breakdown_file.width(18);
8078  Breakdown_file << Surface_CMz[iMarker_Monitoring];
8079  Breakdown_file << " | Pressure (";
8080  Breakdown_file.width(5);
8081  Breakdown_file
8082  << SU2_TYPE::Int(
8083  (Surface_CMz_Inv[iMarker_Monitoring] * 100.0)
8084  / (Surface_CMz[iMarker_Monitoring] + EPS));
8085  Breakdown_file << "%): ";
8086  Breakdown_file.width(18);
8087  Breakdown_file << Surface_CMz_Inv[iMarker_Monitoring];
8088  Breakdown_file << " | Friction (";
8089  Breakdown_file.width(5);
8090  Breakdown_file
8091  << SU2_TYPE::Int(
8092  (Surface_CMz_Visc[iMarker_Monitoring] * 100.0)
8093  / (Surface_CMz[iMarker_Monitoring] + EPS));
8094  Breakdown_file << "%): ";
8095  Breakdown_file.width(18);
8096  Breakdown_file
8097  << Surface_CMz_Visc[iMarker_Monitoring];
8098  Breakdown_file << " | Momentum (";
8099  Breakdown_file.width(5);
8100  Breakdown_file
8101  << SU2_TYPE::Int(
8102  (Surface_CMz_Mnt[iMarker_Monitoring] * 100.0)
8103  / (Surface_CMz[iMarker_Monitoring] + EPS));
8104  Breakdown_file << "%): ";
8105  Breakdown_file.width(18);
8106  Breakdown_file
8107  << Surface_CMz_Mnt[iMarker_Monitoring] << "\n";
8108 
8109  Breakdown_file << "Total CFx (";
8110  Breakdown_file.width(5);
8111  Breakdown_file
8112  << SU2_TYPE::Int((Surface_CFx[iMarker_Monitoring] * 100.0) / (Total_CFx + EPS));
8113  Breakdown_file << "%): ";
8114  Breakdown_file.width(18);
8115  Breakdown_file << Surface_CFx[iMarker_Monitoring];
8116  Breakdown_file << " | Pressure (";
8117  Breakdown_file.width(5);
8118  Breakdown_file
8119  << SU2_TYPE::Int(
8120  (Surface_CFx_Inv[iMarker_Monitoring] * 100.0)
8121  / (Surface_CFx[iMarker_Monitoring] + EPS));
8122  Breakdown_file << "%): ";
8123  Breakdown_file.width(18);
8124  Breakdown_file << Surface_CFx_Inv[iMarker_Monitoring];
8125  Breakdown_file << " | Friction (";
8126  Breakdown_file.width(5);
8127  Breakdown_file
8128  << SU2_TYPE::Int(
8129  (Surface_CFx_Visc[iMarker_Monitoring] * 100.0)
8130  / (Surface_CFx[iMarker_Monitoring] + EPS));
8131  Breakdown_file << "%): ";
8132  Breakdown_file.width(18);
8133  Breakdown_file
8134  << Surface_CFx_Visc[iMarker_Monitoring];
8135  Breakdown_file << " | Momentum (";
8136  Breakdown_file.width(5);
8137  Breakdown_file
8138  << SU2_TYPE::Int(
8139  (Surface_CFx_Mnt[iMarker_Monitoring] * 100.0)
8140  / (Surface_CFx[iMarker_Monitoring] + EPS));
8141  Breakdown_file << "%): ";
8142  Breakdown_file.width(18);
8143  Breakdown_file
8144  << Surface_CFx_Mnt[iMarker_Monitoring] << "\n";
8145 
8146  Breakdown_file << "Total CFy (";
8147  Breakdown_file.width(5);
8148  Breakdown_file
8149  << SU2_TYPE::Int((Surface_CFy[iMarker_Monitoring] * 100.0) / (Total_CFy + EPS));
8150  Breakdown_file << "%): ";
8151  Breakdown_file.width(18);
8152  Breakdown_file << Surface_CFy[iMarker_Monitoring];
8153  Breakdown_file << " | Pressure (";
8154  Breakdown_file.width(5);
8155  Breakdown_file
8156  << SU2_TYPE::Int(
8157  (Surface_CFy_Inv[iMarker_Monitoring] * 100.0)
8158  / (Surface_CFy[iMarker_Monitoring] + EPS));
8159  Breakdown_file << "%): ";
8160  Breakdown_file.width(18);
8161  Breakdown_file << Surface_CFy_Inv[iMarker_Monitoring];
8162  Breakdown_file << " | Friction (";
8163  Breakdown_file.width(5);
8164  Breakdown_file
8165  << SU2_TYPE::Int(
8166  (Surface_CFy_Visc[iMarker_Monitoring] * 100.0)
8167  / (Surface_CFy[iMarker_Monitoring] + EPS));
8168  Breakdown_file << "%): ";
8169  Breakdown_file.width(18);
8170  Breakdown_file
8171  << Surface_CFy_Visc[iMarker_Monitoring];
8172  Breakdown_file << " | Momentum (";
8173  Breakdown_file.width(5);
8174  Breakdown_file
8175  << SU2_TYPE::Int(
8176  (Surface_CFy_Mnt[iMarker_Monitoring] * 100.0)
8177  / (Surface_CFy[iMarker_Monitoring] + EPS));
8178  Breakdown_file << "%): ";
8179  Breakdown_file.width(18);
8180  Breakdown_file
8181  << Surface_CFy_Mnt[iMarker_Monitoring] << "\n";
8182 
8183  if (nDim == 3) {
8184  Breakdown_file << "Total CFz (";
8185  Breakdown_file.width(5);
8186  Breakdown_file
8187  << SU2_TYPE::Int(
8188  (Surface_CFz[iMarker_Monitoring] * 100.0) / (Total_CFz + EPS));
8189  Breakdown_file << "%): ";
8190  Breakdown_file.width(18);
8191  Breakdown_file << Surface_CFz[iMarker_Monitoring];
8192  Breakdown_file << " | Pressure (";
8193  Breakdown_file.width(5);
8194  Breakdown_file
8195  << SU2_TYPE::Int(
8196  (Surface_CFz_Inv[iMarker_Monitoring] * 100.0)
8197  / (Surface_CFz[iMarker_Monitoring] + EPS));
8198  Breakdown_file << "%): ";
8199  Breakdown_file.width(18);
8200  Breakdown_file << Surface_CFz_Inv[iMarker_Monitoring];
8201  Breakdown_file << " | Friction (";
8202  Breakdown_file.width(5);
8203  Breakdown_file
8204  << SU2_TYPE::Int(
8205  (Surface_CFz_Visc[iMarker_Monitoring] * 100.0)
8206  / (Surface_CFz[iMarker_Monitoring] + EPS));
8207  Breakdown_file << "%): ";
8208  Breakdown_file.width(18);
8209  Breakdown_file
8210  << Surface_CFz_Visc[iMarker_Monitoring];
8211  Breakdown_file << " | Momentum (";
8212  Breakdown_file.width(5);
8213  Breakdown_file
8214  << SU2_TYPE::Int(
8215  (Surface_CFz_Mnt[iMarker_Monitoring] * 100.0)
8216  / (Surface_CFz[iMarker_Monitoring] + EPS));
8217  Breakdown_file << "%): ";
8218  Breakdown_file.width(18);
8219  Breakdown_file
8220  << Surface_CFz_Mnt[iMarker_Monitoring] << "\n";
8221 
8222  }
8223 
8224  Breakdown_file << "\n";
8225 
8226 
8227  }
8228 
8229  delete [] Surface_CL;
8230  delete [] Surface_CD;
8231  delete [] Surface_CSF;
8232  delete [] Surface_CEff;
8233  delete [] Surface_CFx;
8234  delete [] Surface_CFy;
8235  delete [] Surface_CFz;
8236  delete [] Surface_CMx;
8237  delete [] Surface_CMy;
8238  delete [] Surface_CMz;
8239 
8240  delete [] Surface_CL_Inv;
8241  delete [] Surface_CD_Inv;
8242  delete [] Surface_CSF_Inv;
8243  delete [] Surface_CEff_Inv;
8244  delete [] Surface_CFx_Inv;
8245  delete [] Surface_CFy_Inv;
8246  delete [] Surface_CFz_Inv;
8247  delete [] Surface_CMx_Inv;
8248  delete [] Surface_CMy_Inv;
8249  delete [] Surface_CMz_Inv;
8250 
8251  delete [] Surface_CL_Visc;
8252  delete [] Surface_CD_Visc;
8253  delete [] Surface_CSF_Visc;
8254  delete [] Surface_CEff_Visc;
8255  delete [] Surface_CFx_Visc;
8256  delete [] Surface_CFy_Visc;
8257  delete [] Surface_CFz_Visc;
8258  delete [] Surface_CMx_Visc;
8259  delete [] Surface_CMy_Visc;
8260  delete [] Surface_CMz_Visc;
8261 
8262  delete [] Surface_CL_Mnt;
8263  delete [] Surface_CD_Mnt;
8264  delete [] Surface_CSF_Mnt;
8265  delete [] Surface_CEff_Mnt;
8266  delete [] Surface_CFx_Mnt;
8267  delete [] Surface_CFy_Mnt;
8268  delete [] Surface_CFz_Mnt;
8269  delete [] Surface_CMx_Mnt;
8270  delete [] Surface_CMy_Mnt;
8271  delete [] Surface_CMz_Mnt;
8272 
8273  Breakdown_file.close();
8274 
8275  }
8276 
8277 }
8278 
8279 void COutput::SetResult_Files(CSolver *****solver_container, CGeometry ****geometry, CConfig **config,
8280  unsigned long iExtIter, unsigned short val_nZone) {
8281 
8282  unsigned short iZone;
8283 
8284  for (iZone = 0; iZone < val_nZone; iZone++) {
8285 
8286  /*--- Flags identifying the types of files to be written. ---*/
8287 
8288  bool Wrt_Vol = config[iZone]->GetWrt_Vol_Sol();
8289  bool Wrt_Srf = config[iZone]->GetWrt_Srf_Sol();
8290  bool Wrt_Csv = config[iZone]->GetWrt_Csv_Sol();
8291 
8292 #ifdef HAVE_MPI
8293  /*--- Do not merge the volume solutions if we are running in parallel.
8294  Force the use of SU2_SOL to merge the volume sols in this case. ---*/
8295 
8297  if (size > SINGLE_NODE) {
8298  Wrt_Vol = false;
8299  Wrt_Srf = false;
8300  }
8301 #endif
8302 
8303  if (rank == MASTER_NODE) cout << endl << "Writing comma-separated values (CSV) surface files." << endl;
8304 
8305  switch (config[iZone]->GetKind_Solver()) {
8306 
8307  case EULER : case NAVIER_STOKES : case RANS :
8308  case FEM_EULER : case FEM_NAVIER_STOKES : case FEM_RANS : case FEM_LES :
8309 
8310  if (Wrt_Csv) SetSurfaceCSV_Flow(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0][FLOW_SOL], iExtIter, iZone, INST_0);
8311  break;
8312 
8313 
8315  if (Wrt_Csv) SetSurfaceCSV_Adjoint(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0][ADJFLOW_SOL], solver_container[iZone][INST_0][MESH_0][FLOW_SOL], iExtIter, iZone, INST_0);
8316  break;
8317 
8318  }
8319 
8320  /*--- Get the file output format ---*/
8321 
8322  unsigned short FileFormat = config[iZone]->GetOutput_FileFormat();
8323 
8324  /*--- Merge the node coordinates and connectivity, if necessary. This
8325  is only performed if a volume solution file is requested, and it
8326  is active by default. ---*/
8327 
8328  if (Wrt_Vol || Wrt_Srf) {
8329  if (rank == MASTER_NODE) cout << "Merging connectivities in the Master node." << endl;
8330  MergeConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], iZone);
8331  }
8332 
8333  /*--- Merge coordinates of all grid nodes (excluding ghost points).
8334  The grid coordinates are always merged and included first in the
8335  restart files. ---*/
8336 
8337  if (rank == MASTER_NODE) cout << "Merging coordinates in the Master node." << endl;
8338  MergeCoordinates(config[iZone], geometry[iZone][INST_0][MESH_0]);
8339 
8340  if ((rank == MASTER_NODE) && (Wrt_Vol || Wrt_Srf)) {
8341  if (FileFormat == TECPLOT_BINARY) {
8342  if (rank == MASTER_NODE) cout << "Writing Tecplot binary volume and surface mesh files." << endl;
8343  SetTecplotBinary_DomainMesh(config[iZone], geometry[iZone][INST_0][MESH_0], iZone);
8344  SetTecplotBinary_SurfaceMesh(config[iZone], geometry[iZone][INST_0][MESH_0], iZone);
8345  if (!wrote_base_file)
8346  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], false);
8347  if (!wrote_surf_file)
8348  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], wrote_surf_file);
8349  }
8350  }
8351 
8352  /*--- Merge the solution data needed for volume solutions and restarts ---*/
8353 
8354  if (rank == MASTER_NODE) cout << "Merging solution in the Master node." << endl;
8355  MergeSolution(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0], iZone);
8356 
8357  /*--- Write restart, or Tecplot files using the merged data.
8358  This data lives only on the master, and these routines are currently
8359  executed by the master proc alone (as if in serial). ---*/
8360 
8361  if (rank == MASTER_NODE) {
8362 
8363  /*--- Write a native restart file ---*/
8364 
8365  if (rank == MASTER_NODE) cout << "Writing SU2 native restart file." << endl;
8366  SetRestart(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0] , iZone);
8367 
8368  if (Wrt_Vol) {
8369 
8370  switch (FileFormat) {
8371 
8372  case TECPLOT:
8373 
8374  /*--- Write a Tecplot ASCII file ---*/
8375 
8376  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file volume solution file." << endl;
8377  SetTecplotASCII(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0], iZone, val_nZone, false);
8378  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], false);
8379  break;
8380 
8381  case FIELDVIEW:
8382 
8383  /*--- Write a FieldView ASCII file ---*/
8384 
8385  if (rank == MASTER_NODE) cout << "Writing FieldView ASCII file volume solution file." << endl;
8386  SetFieldViewASCII(config[iZone], geometry[iZone][INST_0][MESH_0], iZone, val_nZone);
8387  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], false);
8388  break;
8389 
8390  case TECPLOT_BINARY:
8391 
8392  /*--- Write a Tecplot binary solution file ---*/
8393 
8394  if (rank == MASTER_NODE) cout << "Writing Tecplot binary volume solution file." << endl;
8395  SetTecplotBinary_DomainSolution(config[iZone], geometry[iZone][INST_0][MESH_0], iZone);
8396  break;
8397 
8398  case FIELDVIEW_BINARY:
8399 
8400  /*--- Write a FieldView binary file ---*/
8401 
8402  if (rank == MASTER_NODE) cout << "Writing FieldView binary file volume solution file." << endl;
8403  SetFieldViewBinary(config[iZone], geometry[iZone][INST_0][MESH_0], iZone, val_nZone);
8404  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], false);
8405  break;
8406 
8407  case PARAVIEW:
8408 
8409  /*--- Write a Paraview ASCII file ---*/
8410 
8411  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII volume solution file." << endl;
8412  SetParaview_ASCII(config[iZone], geometry[iZone][INST_0][MESH_0], iZone, val_nZone, false);
8413  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], false);
8414  break;
8415 
8416  case PARAVIEW_BINARY:
8417 
8418  /*--- Write a ParaView ASCII file instead for now in serial. ---*/
8419 
8420  if (rank == MASTER_NODE) cout << "ParaView binary volume files not available in this mode." << endl;
8421  if (rank == MASTER_NODE) cout << " Writing ParaView ASCII volume solution file instead." << endl;
8422  SetParaview_ASCII(config[iZone], geometry[iZone][INST_0][MESH_0], iZone, val_nZone, false);
8423  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], false);
8424  break;
8425 
8426  default:
8427  break;
8428  }
8429 
8430  }
8431 
8432  if (Wrt_Srf) {
8433 
8434  switch (FileFormat) {
8435 
8436  case TECPLOT:
8437 
8438  /*--- Write a Tecplot ASCII file ---*/
8439 
8440  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII surface solution file." << endl;
8441  SetTecplotASCII(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0] , iZone, val_nZone, true);
8442  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], true);
8443  break;
8444 
8445  case TECPLOT_BINARY:
8446 
8447  /*--- Write a Tecplot binary solution file ---*/
8448 
8449  if (rank == MASTER_NODE) cout << "Writing Tecplot binary surface solution file." << endl;
8450  SetTecplotBinary_SurfaceSolution(config[iZone], geometry[iZone][INST_0][MESH_0], iZone);
8451  break;
8452 
8453  case PARAVIEW:
8454 
8455  /*--- Write a Paraview ASCII file ---*/
8456 
8457  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII surface solution file." << endl;
8458  SetParaview_ASCII(config[iZone], geometry[iZone][INST_0][MESH_0], iZone, val_nZone, true);
8459  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], true);
8460  break;
8461 
8462  case PARAVIEW_BINARY:
8463 
8464  /*--- Write a ParaView ASCII file instead for now in serial. ---*/
8465 
8466  if (rank == MASTER_NODE) cout << "ParaView binary surface files not available in this mode." << endl;
8467  if (rank == MASTER_NODE) cout << " Writing ParaView ASCII surface solution file instead." << endl;
8468  SetParaview_ASCII(config[iZone], geometry[iZone][INST_0][MESH_0], iZone, val_nZone, true);
8469  DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], true);
8470  break;
8471 
8472  default:
8473  break;
8474  }
8475 
8476  }
8477 
8478  /*--- Release memory needed for merging the solution data. ---*/
8479 
8480  DeallocateCoordinates(config[iZone], geometry[iZone][INST_0][MESH_0]);
8481  DeallocateSolution(config[iZone], geometry[iZone][INST_0][MESH_0]);
8482 
8483  }
8484 
8485  /*--- Final broadcast (informing other procs that the base output
8486  file was written). ---*/
8487 
8488 #ifdef HAVE_MPI
8491 #endif
8492 
8493  }
8494 }
8495 
8496 void COutput::SetBaselineResult_Files(CSolver ***solver, CGeometry ***geometry, CConfig **config,
8497  unsigned long iExtIter, unsigned short val_nZone) {
8498 
8499  unsigned short iZone, iInst, nInst;
8500 
8501  for (iZone = 0; iZone < val_nZone; iZone++) {
8502 
8503  nInst = config[iZone]->GetnTimeInstances();
8504 
8505  for (iInst = 0; iInst < nInst; iInst++) {
8506 
8507  config[iZone]->SetiInst(iInst);
8508 
8509  /*--- Flags identifying the types of files to be written. ---*/
8510 
8511  bool Wrt_Vol = config[iZone]->GetWrt_Vol_Sol();
8512  if (config[iZone]->GetKind_SU2() == SU2_DOT) { Wrt_Vol = false; }
8513  bool Wrt_Srf = config[iZone]->GetWrt_Srf_Sol();
8514 
8515  /*--- Get the file output format ---*/
8516 
8517  unsigned short FileFormat = config[iZone]->GetOutput_FileFormat();
8518 
8519  /*--- Merge the node coordinates and connectivity if necessary. This
8520  is only performed if a volume solution file is requested, and it
8521  is active by default. ---*/
8522 
8523  if ((Wrt_Vol || Wrt_Srf)) {
8524  if (rank == MASTER_NODE) cout << "Merging connectivities in the Master node." << endl;
8525  MergeConnectivity(config[iZone], geometry[iZone][iInst], iZone);
8526  }
8527 
8528  /*--- Merge the solution data needed for volume solutions and restarts ---*/
8529 
8530  if ((Wrt_Vol || Wrt_Srf)) {
8531  if (rank == MASTER_NODE) cout << "Merging solution in the Master node." << endl;
8532  MergeBaselineSolution(config[iZone], geometry[iZone][iInst], solver[iZone][iInst], iZone);
8533  }
8534 
8535  /*--- Write restart, Tecplot or Paraview files using the merged data.
8536  This data lives only on the master, and these routines are currently
8537  executed by the master proc alone (as if in serial). ---*/
8538 
8539 
8540  if (rank == MASTER_NODE) {
8541 
8542  if (Wrt_Vol) {
8543 
8544  switch (FileFormat) {
8545 
8546  case TECPLOT:
8547 
8548  /*--- Write a Tecplot ASCII file ---*/
8549 
8550  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file (volume grid)." << endl;
8551  SetTecplotASCII(config[iZone], geometry[iZone][iInst], &solver[iZone][iInst], iZone, val_nZone, false);
8552  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
8553  break;
8554 
8555  case FIELDVIEW:
8556 
8557  /*--- Write a FieldView ASCII file ---*/
8558 
8559  if (rank == MASTER_NODE) cout << "Writing FieldView ASCII file (volume grid)." << endl;
8560  SetFieldViewASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone);
8561  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
8562  break;
8563 
8564  case TECPLOT_BINARY:
8565 
8566  /*--- Write a Tecplot binary solution file ---*/
8567 
8568  if (rank == MASTER_NODE) cout << "Writing Tecplot Binary file (volume grid)." << endl;
8569  SetTecplotBinary_DomainMesh(config[iZone], geometry[iZone][iInst], iZone);
8570  SetTecplotBinary_DomainSolution(config[iZone], geometry[iZone][iInst], iZone);
8571  break;
8572 
8573  case FIELDVIEW_BINARY:
8574 
8575  /*--- Write a binary binary file ---*/
8576 
8577  if (rank == MASTER_NODE) cout << "Writing FieldView ASCII file (volume grid)." << endl;
8578  SetFieldViewBinary(config[iZone], geometry[iZone][iInst], iZone, val_nZone);
8579  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
8580  break;
8581 
8582  case PARAVIEW:
8583 
8584  /*--- Write a Paraview ASCII file ---*/
8585 
8586  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII file (volume grid)." << endl;
8587  SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, false);
8588  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
8589  break;
8590 
8591  case PARAVIEW_BINARY:
8592 
8593  /*--- Write a ParaView ASCII file instead for now in serial. ---*/
8594 
8595  if (rank == MASTER_NODE) cout << "ParaView binary volume files not available in this mode." << endl;
8596  if (rank == MASTER_NODE) cout << " Writing ParaView ASCII volume solution file instead." << endl;
8597  SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, false);
8598  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
8599  break;
8600 
8601  default:
8602  break;
8603  }
8604 
8605  }
8606 
8607  if (Wrt_Srf) {
8608 
8609  switch (FileFormat) {
8610 
8611  case TECPLOT:
8612 
8613  /*--- Write a Tecplot ASCII file ---*/
8614 
8615  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file (surface grid)." << endl;
8616  SetTecplotASCII(config[iZone], geometry[iZone][iInst], &solver[iZone][iInst], iZone, val_nZone, true);
8617  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], true);
8618  break;
8619 
8620  case TECPLOT_BINARY:
8621 
8622  /*--- Write a Tecplot binary solution file ---*/
8623 
8624  if (rank == MASTER_NODE) cout << "Writing Tecplot Binary file (surface grid)." << endl;
8625  SetTecplotBinary_SurfaceMesh(config[iZone], geometry[iZone][iInst], iZone);
8626  SetTecplotBinary_SurfaceSolution(config[iZone], geometry[iZone][iInst], iZone);
8627  break;
8628 
8629  case PARAVIEW:
8630 
8631  /*--- Write a Paraview ASCII file ---*/
8632 
8633  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII file (surface grid)." << endl;
8634  SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, true);
8635  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], true);
8636  break;
8637 
8638  case PARAVIEW_BINARY:
8639 
8640  /*--- Write a ParaView ASCII file instead for now in serial. ---*/
8641 
8642  if (rank == MASTER_NODE) cout << "ParaView binary surface files not available in this mode." << endl;
8643  if (rank == MASTER_NODE) cout << " Writing ParaView ASCII surface solution file instead." << endl;
8644  SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, true);
8645  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], true);
8646  break;
8647 
8648  default:
8649  break;
8650  }
8651  }
8652 
8653  if (FileFormat == TECPLOT_BINARY) {
8654  if (!wrote_base_file)
8655  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
8656  if (!wrote_surf_file)
8657  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], wrote_surf_file);
8658  }
8659 
8660  if (Wrt_Vol || Wrt_Srf)
8661  DeallocateSolution(config[iZone], geometry[iZone][iInst]);
8662  }
8663 
8664 
8665 
8666  /*--- Final broadcast (informing other procs that the base output
8667  file was written). ---*/
8668 
8669 #ifdef HAVE_MPI
8671 #endif
8672 
8673  }
8674 
8675  }
8676 }
8677 
8678 void COutput::SetMesh_Files(CGeometry **geometry, CConfig **config, unsigned short val_nZone, bool new_file, bool su2_file) {
8679 
8680  char cstr[MAX_STRING_SIZE], out_file[MAX_STRING_SIZE];
8681  unsigned short iZone;
8682  ofstream output_file;
8683  string str;
8684 
8685  /*--- Read the name of the output and input file ---*/
8686 
8687  if (su2_file) {
8688  if (rank == MASTER_NODE) {
8689  str = config[ZONE_0]->GetMesh_Out_FileName();
8690  strcpy (out_file, str.c_str());
8691  strcpy (cstr, out_file);
8692  output_file.precision(15);
8693  output_file.open(cstr, ios::out);
8694  if (val_nZone > 1) {
8695  output_file << "NZONE= " << val_nZone << endl;
8696  }
8697  }
8698  }
8699 
8700  for (iZone = 0; iZone < val_nZone; iZone++) {
8701 
8702  /*--- Flags identifying the types of files to be written. ---*/
8703 
8704  bool Wrt_Vol = config[iZone]->GetVisualize_Volume_Def();
8705  bool Wrt_Srf = config[iZone]->GetVisualize_Surface_Def();
8706  bool Wrt_Crd = config[iZone]->GetWrt_Crd_Sol();
8707 
8708  /*--- Merge the node coordinates and connectivity if necessary. This
8709  is only performed if a volume solution file is requested, and it
8710  is active by default. ---*/
8711 
8712  if (rank == MASTER_NODE) cout <<"Merging grid connectivity." << endl;
8713  MergeConnectivity(config[iZone], geometry[iZone], iZone);
8714 
8715  /*--- Merge coordinates of all grid nodes (excluding ghost points).
8716  The grid coordinates are always merged and included first in the
8717  restart files. ---*/
8718 
8719  if (rank == MASTER_NODE) cout <<"Merging grid coordinates." << endl;
8720  MergeCoordinates(config[iZone], geometry[iZone]);
8721 
8722  /*--- Write restart, Tecplot or Paraview files using the merged data.
8723  This data lives only on the master, and these routines are currently
8724  executed by the master proc alone (as if in serial). ---*/
8725 
8726  if (rank == MASTER_NODE) {
8727 
8728  if (Wrt_Vol) {
8729 
8730  if (rank == MASTER_NODE) cout <<"Writing volume mesh file." << endl;
8731 
8732  /*--- Write a Tecplot ASCII file ---*/
8733 
8734  if (config[iZone]->GetOutput_FileFormat() == PARAVIEW) SetParaview_MeshASCII(config[iZone], geometry[iZone], iZone, val_nZone, false, new_file);
8735  else if (config[iZone]->GetOutput_FileFormat() == PARAVIEW_BINARY) {
8736  if (rank == MASTER_NODE) cout <<"Writing ASCII paraview volume mesh file by default." << endl;
8737  SetParaview_MeshASCII(config[iZone], geometry[iZone], iZone, val_nZone, false, new_file);
8738  }
8739  else if (config[iZone]->GetOutput_FileFormat() == TECPLOT) SetTecplotASCII_Mesh(config[iZone], geometry[iZone], iZone, false, new_file);
8740  else if (config[iZone]->GetOutput_FileFormat() == TECPLOT_BINARY) {
8741  if (rank == MASTER_NODE) cout <<"Writing ASCII tecplot volume mesh file by default." << endl;
8742  SetTecplotASCII_Mesh(config[iZone], geometry[iZone], iZone, false, new_file);
8743  }
8744 
8745  }
8746 
8747  if (Wrt_Srf) {
8748 
8749  if (rank == MASTER_NODE) cout <<"Writing surface mesh file." << endl;
8750 
8751  /*--- Write a Tecplot ASCII file ---*/
8752 
8753  if (config[iZone]->GetOutput_FileFormat() == PARAVIEW) SetParaview_MeshASCII(config[iZone], geometry[iZone], iZone, val_nZone, true, new_file);
8754  else if (config[iZone]->GetOutput_FileFormat() == PARAVIEW_BINARY) {
8755  if (rank == MASTER_NODE) cout <<"Writing ASCII paraview surface mesh file by default." << endl;
8756  SetParaview_MeshASCII(config[iZone], geometry[iZone], iZone, val_nZone, true, new_file);
8757  }
8758  else if (config[iZone]->GetOutput_FileFormat() == TECPLOT) SetTecplotASCII_Mesh(config[iZone], geometry[iZone], iZone, true, new_file);
8759  else if (config[iZone]->GetOutput_FileFormat() == TECPLOT_BINARY) {
8760  if (rank == MASTER_NODE) cout <<"Writing ASCII tecplot surface mesh file by default." << endl;
8761  SetTecplotASCII_Mesh(config[iZone], geometry[iZone], iZone, true, new_file);
8762  }
8763 
8764  }
8765 
8766  /*--- Write a .su2 ASCII file ---*/
8767 
8768  if (su2_file) {
8769 
8770  if (rank == MASTER_NODE) cout <<"Writing .su2 file." << endl;
8771 
8772  SetSU2_MeshASCII(config[iZone], geometry[iZone], iZone, output_file);
8773 
8774  /*--- Write an stl surface file ---*/
8775 
8776  if (rank == MASTER_NODE) cout <<"Writing .stl surface file." << endl;
8777 
8778  SetSTL_MeshASCII(config[iZone], geometry[iZone]);
8779 
8780  }
8781 
8782  /*--- Write a binary file with the grid coordinates alone. ---*/
8783 
8784  if (Wrt_Crd) {
8785  if (rank == MASTER_NODE) cout <<"Writing .dat binary coordinates file." << endl;
8786  WriteCoordinates_Binary(config[iZone], geometry[iZone], iZone);
8787  }
8788 
8789 
8790  /*--- Deallocate connectivity ---*/
8791 
8792  DeallocateConnectivity(config[iZone], geometry[iZone], true);
8793  DeallocateConnectivity(config[iZone], geometry[iZone], false);
8794  DeallocateCoordinates(config[iZone], geometry[iZone]);
8795 
8796  }
8797 
8798  /*--- Final broadcast (informing other procs that the base output
8799  file was written). ---*/
8800 
8801 #ifdef HAVE_MPI
8803 #endif
8804 
8805  /*--- Write an csv surface file, done in parallel ---*/
8806 
8807  if (rank == MASTER_NODE) cout <<"Writing .csv surface file." << endl;
8808 
8809  if (su2_file) SetCSV_MeshASCII(config[iZone], geometry[iZone]);
8810 
8811  }
8812 
8813  if (rank == MASTER_NODE) {
8814  if (su2_file){
8815  output_file.close();
8816  }
8817  }
8818 }
8819 
8820 void COutput::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, CConfig *config, bool output) {
8821 
8822  short iSection, nSection;
8823  unsigned long iVertex, iPoint, Trailing_Point;
8824  su2double *Plane_P0, *Plane_P0_, *Plane_Normal, *Plane_Normal_, *CPressure,
8825  Force[3], ForceInviscid[3], MomentInviscid[3] =
8826  { 0.0, 0.0, 0.0 }, MomentDist[3] = { 0.0, 0.0, 0.0 }, RefDensity,
8827  RefPressure, RefArea, *Velocity_Inf, Gas_Constant, Mach2Vel,
8828  Mach_Motion, Gamma, RefVel2 = 0.0, factor, NDPressure, *Origin,
8829  RefLength, Alpha, CL_Inv,
8830  Xcoord_LeadingEdge = 0.0, Ycoord_LeadingEdge = 0.0, Zcoord_LeadingEdge = 0.0,
8831  Xcoord_TrailingEdge = 0.0, Ycoord_TrailingEdge = 0.0, Zcoord_TrailingEdge = 0.0,
8832  Xcoord_LeadingEdge_ = 0.0,
8833  Xcoord_TrailingEdge_ = 0.0, Ycoord_TrailingEdge_ = 0.0, Zcoord_TrailingEdge_ = 0.0,
8834  MaxDistance, Distance, Chord, Aux, Dihedral_Trailing;
8835 
8836  su2double B, Y, C_L, C_L0, Elliptic_Spanload;
8837 
8838  vector<su2double> Xcoord_Airfoil, Ycoord_Airfoil, Zcoord_Airfoil,
8839  CPressure_Airfoil;
8840  vector<su2double> Xcoord_Airfoil_, Ycoord_Airfoil_, Zcoord_Airfoil_,
8841  CPressure_Airfoil_;
8842  string Marker_Tag, Slice_Filename, Slice_Ext;
8843  ofstream Cp_File;
8844  unsigned short iDim;
8845 
8846  bool grid_movement = config->GetGrid_Movement();
8847 
8848  Plane_P0 = new su2double[3];
8849  Plane_P0_ = new su2double[3];
8850  Plane_Normal = new su2double[3];
8851  Plane_Normal_ = new su2double[3];
8852  CPressure = new su2double[geometry->GetnPoint()];
8853 
8854  if ((rank == MASTER_NODE) && (output)) {
8855  cout << endl << "Writing the spanload file (load_distribution.dat).";
8856  }
8857 
8858  /*--- Compute some reference quantities and necessary values ---*/
8859 
8860  RefDensity = solver->GetDensity_Inf();
8861  RefPressure = solver->GetPressure_Inf();
8862  RefArea = config->GetRefArea();
8863  Velocity_Inf = solver->GetVelocity_Inf();
8864  Gamma = config->GetGamma();
8865  Origin = config->GetRefOriginMoment(0);
8866  RefLength = config->GetRefLength();
8867  Alpha = config->GetAoA() * PI_NUMBER / 180.0;
8868 
8869  if (grid_movement) {
8870  Gas_Constant = config->GetGas_ConstantND();
8871  Mach2Vel = sqrt(
8872  Gamma * Gas_Constant * config->GetTemperature_FreeStreamND());
8873  Mach_Motion = config->GetMach_Motion();
8874  RefVel2 = (Mach_Motion * Mach2Vel) * (Mach_Motion * Mach2Vel);
8875  } else {
8876  RefVel2 = 0.0;
8877  for (iDim = 0; iDim < geometry->GetnDim(); iDim++)
8878  RefVel2 += Velocity_Inf[iDim] * Velocity_Inf[iDim];
8879  }
8880  factor = 1.0 / (0.5 * RefDensity * RefArea * RefVel2);
8881 
8882  if (geometry->GetnDim() == 3) {
8883 
8884  /*--- Copy the pressure to an auxiliar structure ---*/
8885 
8886  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
8887  CPressure[iPoint] = (solver->node[iPoint]->GetPressure()
8888  - RefPressure) * factor * RefArea;
8889  }
8890 
8891  nSection = config->GetnLocationStations();
8892 
8893  for (iSection = 0; iSection < nSection; iSection++) {
8894 
8895  /*--- Read the values from the config file ---*/
8896 
8897  Plane_Normal[0] = 0.0; Plane_P0[0] = 0.0;
8898  Plane_Normal[1] = 0.0; Plane_P0[1] = 0.0;
8899  Plane_Normal[2] = 0.0; Plane_P0[2] = 0.0;
8900 
8901  if (config->GetGeo_Description() == FUSELAGE) {
8902  Plane_Normal[0] = 1.0;
8903  Plane_P0[0] = config->GetLocationStations(iSection);
8904  }
8905  else if (config->GetGeo_Description() == NACELLE) {
8906  Plane_Normal[0] = 0.0;
8907  Plane_Normal[1] = -sin(config->GetLocationStations(iSection)*PI_NUMBER/180.0);
8908  Plane_Normal[2] = cos(config->GetLocationStations(iSection)*PI_NUMBER/180.0);
8909 
8910  /*--- Apply tilt angle to the plane ---*/
8911 
8912  su2double Tilt_Angle = config->GetNacelleLocation(3)*PI_NUMBER/180;
8913  su2double Plane_NormalX_Tilt = Plane_Normal[0]*cos(Tilt_Angle) + Plane_Normal[2]*sin(Tilt_Angle);
8914  su2double Plane_NormalY_Tilt = Plane_Normal[1];
8915  su2double Plane_NormalZ_Tilt = Plane_Normal[2]*cos(Tilt_Angle) - Plane_Normal[0]*sin(Tilt_Angle);
8916 
8917  /*--- Apply toe angle to the plane ---*/
8918 
8919  su2double Toe_Angle = config->GetNacelleLocation(4)*PI_NUMBER/180;
8920  su2double Plane_NormalX_Tilt_Toe = Plane_NormalX_Tilt*cos(Toe_Angle) - Plane_NormalY_Tilt*sin(Toe_Angle);
8921  su2double Plane_NormalY_Tilt_Toe = Plane_NormalX_Tilt*sin(Toe_Angle) + Plane_NormalY_Tilt*cos(Toe_Angle);
8922  su2double Plane_NormalZ_Tilt_Toe = Plane_NormalZ_Tilt;
8923 
8924  /*--- Update normal vector ---*/
8925 
8926  Plane_Normal[0] = Plane_NormalX_Tilt_Toe;
8927  Plane_Normal[1] = Plane_NormalY_Tilt_Toe;
8928  Plane_Normal[2] = Plane_NormalZ_Tilt_Toe;
8929 
8930  }
8931  else {
8932  Plane_Normal[1] = 1.0;
8933  Plane_P0[1] = config->GetLocationStations(iSection);
8934  }
8935 
8936  /*--- Compute the airfoil sections (note that we feed in the Cp) ---*/
8937 
8938  geometry->ComputeAirfoil_Section(Plane_P0, Plane_Normal, -1E6, 1E6, -1E6, 1E6, -1E6, 1E6,
8939  CPressure, Xcoord_Airfoil, Ycoord_Airfoil, Zcoord_Airfoil,
8940  CPressure_Airfoil, true, config);
8941 
8942  if ((rank == MASTER_NODE) && (Xcoord_Airfoil.size() == 0)) {
8943  if ((config->GetGeo_Description() == FUSELAGE) || (config->GetGeo_Description() == WING))
8944  cout << endl << "Please check the config file, the section (" << Plane_P0[0] <<", " << Plane_P0[1] <<", " << Plane_P0[2] << ") has not been detected." << endl;
8945  if (config->GetGeo_Description() == NACELLE)
8946  cout << endl << "Please check the config file, the section (" << Plane_Normal[0] <<", " << Plane_Normal[1] <<", " << Plane_Normal[2] << ") has not been detected." << endl;
8947  }
8948 
8949 
8950  /*--- Compute dihedral using a step in the station value ---*/
8951 
8952  Plane_P0_[0] = 0.0; Plane_Normal_[0] = 0.0;
8953  Plane_P0_[1] = 0.0; Plane_Normal_[1] = 0.0;
8954  Plane_P0_[2] = 0.0; Plane_Normal_[2] = 0.0;
8955 
8956  if (config->GetGeo_Description() == FUSELAGE) {
8957  Plane_Normal_[0] = 1.0;
8958  if (iSection == 0) Plane_P0_[0] = config->GetLocationStations(iSection) + 0.01;
8959  else Plane_P0_[0] = config->GetLocationStations(iSection) - 0.01;
8960  }
8961  else if (config->GetGeo_Description() == NACELLE) {
8962  if (iSection == 0) {
8963  Plane_Normal_[0] = 0.0;
8964  Plane_Normal_[1] = -sin((config->GetLocationStations(iSection) + 0.01)*PI_NUMBER/180.0);
8965  Plane_Normal_[2] = cos((config->GetLocationStations(iSection) + 0.01)*PI_NUMBER/180.0);
8966 
8967  /*--- Apply tilt angle to the plane ---*/
8968 
8969  su2double Tilt_Angle = config->GetNacelleLocation(3)*PI_NUMBER/180;
8970  su2double Plane_NormalX_Tilt = Plane_Normal[0]*cos(Tilt_Angle) + Plane_Normal[2]*sin(Tilt_Angle);
8971  su2double Plane_NormalY_Tilt = Plane_Normal[1];
8972  su2double Plane_NormalZ_Tilt = Plane_Normal[2]*cos(Tilt_Angle) - Plane_Normal[0]*sin(Tilt_Angle);
8973 
8974  /*--- Apply toe angle to the plane ---*/
8975 
8976  su2double Toe_Angle = config->GetNacelleLocation(4)*PI_NUMBER/180;
8977  su2double Plane_NormalX_Tilt_Toe = Plane_NormalX_Tilt*cos(Toe_Angle) - Plane_NormalY_Tilt*sin(Toe_Angle);
8978  su2double Plane_NormalY_Tilt_Toe = Plane_NormalX_Tilt*sin(Toe_Angle) + Plane_NormalY_Tilt*cos(Toe_Angle);
8979  su2double Plane_NormalZ_Tilt_Toe = Plane_NormalZ_Tilt;
8980 
8981  /*--- Update normal vector ---*/
8982 
8983  Plane_Normal[0] = Plane_NormalX_Tilt_Toe;
8984  Plane_Normal[1] = Plane_NormalY_Tilt_Toe;
8985  Plane_Normal[2] = Plane_NormalZ_Tilt_Toe;
8986 
8987  }
8988  else {
8989  Plane_Normal_[0] = 0.0;
8990  Plane_Normal_[1] = -sin((config->GetLocationStations(iSection) - 0.01)*PI_NUMBER/180.0);
8991  Plane_Normal_[2] = cos((config->GetLocationStations(iSection) - 0.01)*PI_NUMBER/180.0);
8992 
8993  /*--- Apply tilt angle to the plane ---*/
8994 
8995  su2double Tilt_Angle = config->GetNacelleLocation(3)*PI_NUMBER/180;
8996  su2double Plane_NormalX_Tilt = Plane_Normal[0]*cos(Tilt_Angle) + Plane_Normal[2]*sin(Tilt_Angle);
8997  su2double Plane_NormalY_Tilt = Plane_Normal[1];
8998  su2double Plane_NormalZ_Tilt = Plane_Normal[2]*cos(Tilt_Angle) - Plane_Normal[0]*sin(Tilt_Angle);
8999 
9000  /*--- Apply toe angle to the plane ---*/
9001 
9002  su2double Toe_Angle = config->GetNacelleLocation(4)*PI_NUMBER/180;
9003  su2double Plane_NormalX_Tilt_Toe = Plane_NormalX_Tilt*cos(Toe_Angle) - Plane_NormalY_Tilt*sin(Toe_Angle);
9004  su2double Plane_NormalY_Tilt_Toe = Plane_NormalX_Tilt*sin(Toe_Angle) + Plane_NormalY_Tilt*cos(Toe_Angle);
9005  su2double Plane_NormalZ_Tilt_Toe = Plane_NormalZ_Tilt;
9006 
9007  /*--- Update normal vector ---*/
9008 
9009  Plane_Normal[0] = Plane_NormalX_Tilt_Toe;
9010  Plane_Normal[1] = Plane_NormalY_Tilt_Toe;
9011  Plane_Normal[2] = Plane_NormalZ_Tilt_Toe;
9012 
9013  }
9014  }
9015  else {
9016  Plane_Normal_[1] = 1.0;
9017  if (iSection == 0) Plane_P0_[1] = config->GetLocationStations(iSection) + 0.01;
9018  else Plane_P0_[1] = config->GetLocationStations(iSection) - 0.01;
9019  }
9020 
9021  geometry->ComputeAirfoil_Section(Plane_P0_, Plane_Normal_, -1E6, 1E6, -1E6, 1E6, -1E6, 1E6,
9022  CPressure, Xcoord_Airfoil_, Ycoord_Airfoil_, Zcoord_Airfoil_,
9023  CPressure_Airfoil_, true, config);
9024 
9025  /*--- Output the pressure on each section (tecplot format) ---*/
9026 
9027  if ((rank == MASTER_NODE) && (Xcoord_Airfoil.size() != 0)) {
9028 
9029  /*--- Find leading and trailing edge ---*/
9030 
9031  Xcoord_LeadingEdge = 1E6; Xcoord_TrailingEdge = -1E6;
9032  for (iVertex = 0; iVertex < Xcoord_Airfoil.size(); iVertex++) {
9033  if (Xcoord_Airfoil[iVertex] < Xcoord_LeadingEdge) {
9034  Xcoord_LeadingEdge = Xcoord_Airfoil[iVertex];
9035  Ycoord_LeadingEdge = Ycoord_Airfoil[iVertex];
9036  Zcoord_LeadingEdge = Zcoord_Airfoil[iVertex];
9037  }
9038  if (Xcoord_Airfoil[iVertex] > Xcoord_TrailingEdge) {
9039  Xcoord_TrailingEdge = Xcoord_Airfoil[iVertex];
9040  Ycoord_TrailingEdge = Ycoord_Airfoil[iVertex];
9041  Zcoord_TrailingEdge = Zcoord_Airfoil[iVertex];
9042  }
9043  }
9044 
9045  Chord = (Xcoord_TrailingEdge-Xcoord_LeadingEdge);
9046 
9047  /*--- Compute dihedral ---*/
9048 
9049  Xcoord_LeadingEdge_ = 1E6; Xcoord_TrailingEdge_ = -1E6;
9050  for (iVertex = 0; iVertex < Xcoord_Airfoil_.size(); iVertex++) {
9051  if (Xcoord_Airfoil_[iVertex] < Xcoord_LeadingEdge_) {
9052  Xcoord_LeadingEdge_ = Xcoord_Airfoil_[iVertex];
9053  }
9054  if (Xcoord_Airfoil_[iVertex] > Xcoord_TrailingEdge_) {
9055  Xcoord_TrailingEdge_ = Xcoord_Airfoil_[iVertex];
9056  Ycoord_TrailingEdge_ = Ycoord_Airfoil_[iVertex];
9057  Zcoord_TrailingEdge_ = Zcoord_Airfoil_[iVertex];
9058  }
9059  }
9060 
9061  if (iSection == 0) {
9062  Dihedral_Trailing = atan((Zcoord_TrailingEdge_ - Zcoord_TrailingEdge) / (Ycoord_TrailingEdge_ - Ycoord_TrailingEdge))*180/PI_NUMBER;
9063  }
9064  else {
9065  Dihedral_Trailing = atan((Zcoord_TrailingEdge - Zcoord_TrailingEdge_) / (Ycoord_TrailingEdge - Ycoord_TrailingEdge_))*180/PI_NUMBER;
9066  }
9067 
9068  /*--- Write Cp at each section (tecplot format) ---*/
9069 
9070  if (output) {
9071 
9072  ofstream Cp_File;
9073 
9074  if (iSection == 0) {
9075  Cp_File.open("cp_sections.dat", ios::out);
9076  Cp_File << "TITLE = \"Airfoil sections\"" << endl;
9077  Cp_File << "VARIABLES = \"x/c\",\"C<sub>p</sub>\",\"x\",\"y\",\"z\",\"y/c\",\"z/c\"" << endl;
9078  } else
9079  Cp_File.open("cp_sections.dat", ios::app);
9080 
9081  if (config->GetGeo_Description() == NACELLE) {
9082  su2double theta_deg = atan2(Plane_Normal[1], -Plane_Normal[2])/PI_NUMBER*180 + 180;
9083  Cp_File << "ZONE T=\"Theta = " << theta_deg << " deg\", I= " << Xcoord_Airfoil.size() << ", F=POINT" << "\n";
9084  }
9085  else {
9086  if (config->GetSystemMeasurements() == SI) Cp_File << "ZONE T=\"y = " << Plane_P0[1] << " m\", I= "
9087  << Xcoord_Airfoil.size() << ", F=POINT" << "\n";
9088 
9089  if (config->GetSystemMeasurements() == US) Cp_File << "ZONE T=\"y = " << Plane_P0[1]*12.0 << " in\", I= "
9090  << Xcoord_Airfoil.size() << ", F=POINT" << "\n";
9091  }
9092 
9093 
9094 
9095  /*--- Coordinates and pressure value ---*/
9096 
9097  for (iVertex = 0; iVertex < Xcoord_Airfoil.size(); iVertex++) {
9098 
9099  su2double XCoord = Xcoord_Airfoil[iVertex];
9100  su2double YCoord = Ycoord_Airfoil[iVertex];
9101  su2double ZCoord = Zcoord_Airfoil[iVertex];
9102 
9103  /*--- Undo the transformation based on the Theta angle ---*/
9104 
9105  if (config->GetGeo_Description() == NACELLE) {
9106  su2double theta_deg = atan2(Plane_Normal[1],-Plane_Normal[2])/PI_NUMBER*180 + 180;
9107  su2double Angle = theta_deg*PI_NUMBER/180 - 0.5*PI_NUMBER;
9108 
9109  XCoord = Xcoord_Airfoil[iVertex] + config->GetNacelleLocation(0);
9110  YCoord = (Ycoord_Airfoil[iVertex]*cos(Angle) - Zcoord_Airfoil[iVertex]*sin(Angle)) + config->GetNacelleLocation(1);
9111  ZCoord = (Zcoord_Airfoil[iVertex]*cos(Angle) + Ycoord_Airfoil[iVertex]*sin(Angle)) + config->GetNacelleLocation(2);
9112 
9113  }
9114 
9115  if (config->GetSystemMeasurements() == US) {
9116  Cp_File << (Xcoord_Airfoil[iVertex] - Xcoord_LeadingEdge) / Chord << " " << CPressure_Airfoil[iVertex]
9117  << " " << XCoord * 12.0 << " " << YCoord * 12.0 << " " << ZCoord * 12.0
9118  << " " << (Ycoord_Airfoil[iVertex] - Ycoord_LeadingEdge) / Chord << " " << (Zcoord_Airfoil[iVertex] - Zcoord_LeadingEdge) / Chord << "\n";
9119  }
9120  else {
9121  Cp_File << (Xcoord_Airfoil[iVertex] - Xcoord_LeadingEdge) / Chord << " " << CPressure_Airfoil[iVertex]
9122  << " " << XCoord << " " << YCoord << " " << ZCoord
9123  << " " << (Ycoord_Airfoil[iVertex] - Ycoord_LeadingEdge) / Chord << " " << (Zcoord_Airfoil[iVertex] - Zcoord_LeadingEdge) / Chord << "\n";
9124  }
9125 
9126  }
9127 
9128  Cp_File.close();
9129 
9130  }
9131 
9132  /*--- Compute load distribution ---*/
9133 
9134  ForceInviscid[0] = 0.0; ForceInviscid[1] = 0.0; ForceInviscid[2] = 0.0; MomentInviscid[1] = 0.0;
9135 
9136  for (iVertex = 0; iVertex < Xcoord_Airfoil.size() - 1; iVertex++) {
9137 
9138  NDPressure = 0.5 * (CPressure_Airfoil[iVertex] + CPressure_Airfoil[iVertex + 1]);
9139 
9140  Force[0] = -(Zcoord_Airfoil[iVertex + 1] - Zcoord_Airfoil[iVertex]) * NDPressure;
9141  Force[1] = 0.0;
9142  Force[2] = (Xcoord_Airfoil[iVertex + 1] - Xcoord_Airfoil[iVertex]) * NDPressure;
9143 
9144  ForceInviscid[0] += Force[0];
9145  ForceInviscid[1] += Force[1];
9146  ForceInviscid[2] += Force[2];
9147 
9148  MomentDist[0] = 0.5 * (Xcoord_Airfoil[iVertex] + Xcoord_Airfoil[iVertex + 1]) - Origin[0];
9149  MomentDist[1] = 0.5 * (Ycoord_Airfoil[iVertex] + Ycoord_Airfoil[iVertex + 1]) - Origin[1];
9150  MomentDist[2] = 0.5 * (Zcoord_Airfoil[iVertex] + Zcoord_Airfoil[iVertex + 1]) - Origin[3];
9151 
9152  MomentInviscid[1] += (Force[0] * MomentDist[2] - Force[2] * MomentDist[0]) / RefLength;
9153 
9154  }
9155 
9156  /*--- Compute local chord, for the nondimensionalization ---*/
9157 
9158  MaxDistance = 0.0; Trailing_Point = 0;
9159 
9160  for (iVertex = 1; iVertex < Xcoord_Airfoil.size(); iVertex++) {
9161 
9162  Distance = sqrt(pow(Xcoord_Airfoil[iVertex] - Xcoord_Airfoil[Trailing_Point], 2.0) +
9163  pow(Ycoord_Airfoil[iVertex] - Ycoord_Airfoil[Trailing_Point], 2.0) +
9164  pow(Zcoord_Airfoil[iVertex] - Zcoord_Airfoil[Trailing_Point], 2.0));
9165 
9166  if (MaxDistance < Distance) { MaxDistance = Distance; }
9167 
9168  }
9169 
9170  Chord = MaxDistance;
9171 
9172  CL_Inv = cos(Dihedral_Trailing * PI_NUMBER / 180.0) * fabs( -ForceInviscid[0] * sin(Alpha) + ForceInviscid[2] * cos(Alpha) )/ Chord;
9173 
9174  /*--- Compute sectional lift at the root ---*/
9175 
9176  B = 2.0*config->GetSemiSpan();
9177  RefArea = config->GetRefArea();
9178  C_L = solver->GetTotal_CL();
9179  C_L0 = 8.0*C_L*RefArea/(B*PI_NUMBER);
9180  Y = Ycoord_Airfoil[0];
9181  Aux = Y/(0.5*B);
9182  Elliptic_Spanload = (C_L0 / RefLength) * sqrt(fabs(1.0-Aux*Aux));
9183 
9184 
9185  /*--- Write load distribution ---*/
9186 
9187  if (output) {
9188 
9189  ofstream Load_File;
9190  if (iSection == 0) {
9191 
9192  if ((config->GetOutput_FileFormat() == PARAVIEW) || (config->GetOutput_FileFormat() == PARAVIEW_BINARY)) {
9193  Load_File.open("load_distribution.csv", ios::out);
9194  Load_File << "\"Percent Semispan\",\"Sectional C_L\",\"Spanload (c C_L / c_ref) \",\"Elliptic Spanload\"" << endl;
9195  }
9196  else {
9197  Load_File.open("load_distribution.dat", ios::out);
9198  Load_File << "TITLE = \"Load distribution\"" << endl;
9199  Load_File << "VARIABLES = \"Percent Semispan\",\"Sectional C<sub>L</sub>\",\"Spanload (c C<sub>L</sub> / c<sub>ref</sub>) \",\"Elliptic Spanload\"" << endl;
9200  Load_File << "ZONE T=\"Wing load distribution\"" << endl;
9201  }
9202  } else {
9203  if ((config->GetOutput_FileFormat() == PARAVIEW) || (config->GetOutput_FileFormat() == PARAVIEW_BINARY)) Load_File.open("load_distribution.csv", ios::app);
9204  else Load_File.open("load_distribution.dat", ios::app);
9205  }
9206 
9207 
9208  /*--- CL and spanload ---*/
9209 
9210  if ((config->GetOutput_FileFormat() == PARAVIEW) || (config->GetOutput_FileFormat() == PARAVIEW_BINARY))
9211  Load_File << 100.0*Ycoord_Airfoil[0]/(0.5*B) << ", " << CL_Inv << ", " << Chord*CL_Inv / RefLength <<", " << Elliptic_Spanload << endl;
9212  else
9213  Load_File << 100.0*Ycoord_Airfoil[0]/(0.5*B) << " " << CL_Inv << " " << Chord*CL_Inv / RefLength <<" " << Elliptic_Spanload << endl;
9214 
9215  Load_File.close();
9216 
9217  }
9218 
9219  }
9220 
9221  }
9222 
9223  }
9224 
9225  /*--- Delete dynamically allocated memory ---*/
9226 
9227  delete[] Plane_P0;
9228  delete[] Plane_P0_;
9229  delete[] Plane_Normal;
9230  delete[] Plane_Normal_;
9231  delete[] CPressure;
9232 
9233 }
9234 
9235 
9236 void COutput::SetCp_InverseDesign(CSolver *solver_container, CGeometry *geometry, CConfig *config, unsigned long iExtIter) {
9237 
9238  unsigned short iMarker, icommas, Boundary, iDim;
9239  unsigned long iVertex, iPoint, (*Point2Vertex)[2], nPointLocal = 0, nPointGlobal = 0;
9240  su2double XCoord, YCoord, ZCoord, Pressure, PressureCoeff = 0, Cp, CpTarget, *Normal = NULL, Area, PressDiff;
9241  bool *PointInDomain;
9242  string text_line, surfCp_filename;
9243  ifstream Surface_file;
9244  char buffer[50], cstr[200];
9245 
9246 
9247  nPointLocal = geometry->GetnPoint();
9248 #ifdef HAVE_MPI
9249  SU2_MPI::Allreduce(&nPointLocal, &nPointGlobal, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
9250 #else
9251  nPointGlobal = nPointLocal;
9252 #endif
9253 
9254  Point2Vertex = new unsigned long[nPointGlobal][2];
9255  PointInDomain = new bool[nPointGlobal];
9256 
9257  for (iPoint = 0; iPoint < nPointGlobal; iPoint ++)
9258  PointInDomain[iPoint] = false;
9259 
9260  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
9261  Boundary = config->GetMarker_All_KindBC(iMarker);
9262 
9263  if ((Boundary == EULER_WALL ) ||
9264  (Boundary == HEAT_FLUX ) ||
9265  (Boundary == ISOTHERMAL ) ||
9266  (Boundary == NEARFIELD_BOUNDARY)) {
9267  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
9268 
9269  /*--- The Pressure file uses the global numbering ---*/
9270 
9271 #ifndef HAVE_MPI
9272  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
9273 #else
9274  iPoint = geometry->node[geometry->vertex[iMarker][iVertex]->GetNode()]->GetGlobalIndex();
9275 #endif
9276 
9277  if (geometry->vertex[iMarker][iVertex]->GetNode() < geometry->GetnPointDomain()) {
9278  Point2Vertex[iPoint][0] = iMarker;
9279  Point2Vertex[iPoint][1] = iVertex;
9280  PointInDomain[iPoint] = true;
9281  solver_container->SetCPressureTarget(iMarker, iVertex, 0.0);
9282  }
9283 
9284  }
9285  }
9286  }
9287 
9288  /*--- Prepare to read the surface pressure files (CSV) ---*/
9289 
9290  surfCp_filename = "TargetCp";
9291  strcpy (cstr, surfCp_filename.c_str());
9292 
9293  /*--- Write file name with extension if unsteady or steady ---*/
9294 
9295  if ((config->GetUnsteady_Simulation() && config->GetWrt_Unsteady()) ||
9296  (config->GetUnsteady_Simulation() == HARMONIC_BALANCE)) {
9297  if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.dat", SU2_TYPE::Int(iExtIter));
9298  if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d.dat", SU2_TYPE::Int(iExtIter));
9299  if ((SU2_TYPE::Int(iExtIter) >= 100) && (SU2_TYPE::Int(iExtIter) < 1000)) SPRINTF (buffer, "_00%d.dat", SU2_TYPE::Int(iExtIter));
9300  if ((SU2_TYPE::Int(iExtIter) >= 1000) && (SU2_TYPE::Int(iExtIter) < 10000)) SPRINTF (buffer, "_0%d.dat", SU2_TYPE::Int(iExtIter));
9301  if (SU2_TYPE::Int(iExtIter) >= 10000) SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(iExtIter));
9302  }
9303  else
9304  SPRINTF (buffer, ".dat");
9305 
9306  strcat (cstr, buffer);
9307 
9308  /*--- Read the surface pressure file ---*/
9309 
9310  string::size_type position;
9311 
9312  Surface_file.open(cstr, ios::in);
9313 
9314  if (!(Surface_file.fail())) {
9315 
9316  getline(Surface_file, text_line);
9317 
9318  while (getline(Surface_file, text_line)) {
9319  for (icommas = 0; icommas < 50; icommas++) {
9320  position = text_line.find( ",", 0 );
9321  if (position!=string::npos) text_line.erase (position,1);
9322  }
9323  stringstream point_line(text_line);
9324 
9325  if (geometry->GetnDim() == 2) point_line >> iPoint >> XCoord >> YCoord >> Pressure >> PressureCoeff;
9326  if (geometry->GetnDim() == 3) point_line >> iPoint >> XCoord >> YCoord >> ZCoord >> Pressure >> PressureCoeff;
9327 
9328  if (PointInDomain[iPoint]) {
9329 
9330  /*--- Find the vertex for the Point and Marker ---*/
9331 
9332  iMarker = Point2Vertex[iPoint][0];
9333  iVertex = Point2Vertex[iPoint][1];
9334 
9335  solver_container->SetCPressureTarget(iMarker, iVertex, PressureCoeff);
9336 
9337  }
9338 
9339  }
9340 
9341  Surface_file.close();
9342 
9343  }
9344 
9345  /*--- Compute the pressure difference ---*/
9346 
9347  PressDiff = 0.0;
9348  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
9349  Boundary = config->GetMarker_All_KindBC(iMarker);
9350 
9351  if ((Boundary == EULER_WALL ) ||
9352  (Boundary == HEAT_FLUX ) ||
9353  (Boundary == ISOTHERMAL ) ||
9354  (Boundary == NEARFIELD_BOUNDARY)) {
9355  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
9356 
9357  Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
9358 
9359  Cp = solver_container->GetCPressure(iMarker, iVertex);
9360  CpTarget = solver_container->GetCPressureTarget(iMarker, iVertex);
9361 
9362  Area = 0.0;
9363  for (iDim = 0; iDim < geometry->GetnDim(); iDim++)
9364  Area += Normal[iDim]*Normal[iDim];
9365  Area = sqrt(Area);
9366 
9367  PressDiff += Area * (CpTarget - Cp) * (CpTarget - Cp);
9368  }
9369 
9370  }
9371  }
9372 
9373 #ifdef HAVE_MPI
9374  su2double MyPressDiff = PressDiff; PressDiff = 0.0;
9375  SU2_MPI::Allreduce(&MyPressDiff, &PressDiff, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
9376 #endif
9377 
9378  /*--- Update the total Cp difference coeffient ---*/
9379 
9380  solver_container->SetTotal_CpDiff(PressDiff);
9381 
9382  delete [] Point2Vertex;
9383  delete [] PointInDomain;
9384 
9385 }
9386 
9387 void COutput::SetHeatFlux_InverseDesign(CSolver *solver_container, CGeometry *geometry, CConfig *config, unsigned long iExtIter) {
9388 
9389  unsigned short iMarker, icommas, Boundary, iDim;
9390  unsigned long iVertex, iPoint, (*Point2Vertex)[2], nPointLocal = 0, nPointGlobal = 0;
9391  su2double XCoord, YCoord, ZCoord, PressureCoeff, HeatFlux = 0.0, HeatFluxDiff, HeatFluxTarget, *Normal = NULL, Area,
9392  Pressure, Cf;
9393  bool *PointInDomain;
9394  string text_line, surfHeatFlux_filename;
9395  ifstream Surface_file;
9396  char buffer[50], cstr[200];
9397 
9398 
9399  nPointLocal = geometry->GetnPoint();
9400 #ifdef HAVE_MPI
9401  SU2_MPI::Allreduce(&nPointLocal, &nPointGlobal, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
9402 #else
9403  nPointGlobal = nPointLocal;
9404 #endif
9405 
9406  Point2Vertex = new unsigned long[nPointGlobal][2];
9407  PointInDomain = new bool[nPointGlobal];
9408 
9409  for (iPoint = 0; iPoint < nPointGlobal; iPoint ++)
9410  PointInDomain[iPoint] = false;
9411 
9412  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
9413  Boundary = config->GetMarker_All_KindBC(iMarker);
9414 
9415  if ((Boundary == EULER_WALL ) ||
9416  (Boundary == HEAT_FLUX ) ||
9417  (Boundary == ISOTHERMAL ) ||
9418  (Boundary == NEARFIELD_BOUNDARY)) {
9419  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
9420 
9421  /*--- The Pressure file uses the global numbering ---*/
9422 
9423 #ifndef HAVE_MPI
9424  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
9425 #else
9426  iPoint = geometry->node[geometry->vertex[iMarker][iVertex]->GetNode()]->GetGlobalIndex();
9427 #endif
9428 
9429  if (geometry->vertex[iMarker][iVertex]->GetNode() < geometry->GetnPointDomain()) {
9430  Point2Vertex[iPoint][0] = iMarker;
9431  Point2Vertex[iPoint][1] = iVertex;
9432  PointInDomain[iPoint] = true;
9433  solver_container->SetHeatFluxTarget(iMarker, iVertex, 0.0);
9434  }
9435  }
9436  }
9437  }
9438 
9439  /*--- Prepare to read the surface pressure files (CSV) ---*/
9440 
9441  surfHeatFlux_filename = "TargetHeatFlux";
9442  strcpy (cstr, surfHeatFlux_filename.c_str());
9443 
9444  /*--- Write file name with extension if unsteady or steady ---*/
9445 
9446  if ((config->GetUnsteady_Simulation() && config->GetWrt_Unsteady()) ||
9447  (config->GetUnsteady_Simulation() == HARMONIC_BALANCE)) {
9448  if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.dat", SU2_TYPE::Int(iExtIter));
9449  if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d.dat", SU2_TYPE::Int(iExtIter));
9450  if ((SU2_TYPE::Int(iExtIter) >= 100) && (SU2_TYPE::Int(iExtIter) < 1000)) SPRINTF (buffer, "_00%d.dat", SU2_TYPE::Int(iExtIter));
9451  if ((SU2_TYPE::Int(iExtIter) >= 1000) && (SU2_TYPE::Int(iExtIter) < 10000)) SPRINTF (buffer, "_0%d.dat", SU2_TYPE::Int(iExtIter));
9452  if (SU2_TYPE::Int(iExtIter) >= 10000) SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(iExtIter));
9453  }
9454  else
9455  SPRINTF (buffer, ".dat");
9456 
9457  strcat (cstr, buffer);
9458 
9459  /*--- Read the surface pressure file ---*/
9460 
9461  string::size_type position;
9462 
9463  Surface_file.open(cstr, ios::in);
9464 
9465  if (!(Surface_file.fail())) {
9466 
9467  getline(Surface_file, text_line);
9468 
9469  while (getline(Surface_file, text_line)) {
9470  for (icommas = 0; icommas < 50; icommas++) {
9471  position = text_line.find( ",", 0 );
9472  if (position!=string::npos) text_line.erase (position,1);
9473  }
9474  stringstream point_line(text_line);
9475 
9476  if (geometry->GetnDim() == 2) point_line >> iPoint >> XCoord >> YCoord >> Pressure >> PressureCoeff >> Cf >> HeatFlux;
9477  if (geometry->GetnDim() == 3) point_line >> iPoint >> XCoord >> YCoord >> ZCoord >> Pressure >> PressureCoeff >> Cf >> HeatFlux;
9478 
9479  if (PointInDomain[iPoint]) {
9480 
9481  /*--- Find the vertex for the Point and Marker ---*/
9482 
9483  iMarker = Point2Vertex[iPoint][0];
9484  iVertex = Point2Vertex[iPoint][1];
9485 
9486  solver_container->SetHeatFluxTarget(iMarker, iVertex, HeatFlux);
9487 
9488  }
9489 
9490  }
9491 
9492  Surface_file.close();
9493  }
9494 
9495  /*--- Compute the pressure difference ---*/
9496 
9497  HeatFluxDiff = 0.0;
9498  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
9499  Boundary = config->GetMarker_All_KindBC(iMarker);
9500 
9501  if ((Boundary == EULER_WALL ) ||
9502  (Boundary == HEAT_FLUX ) ||
9503  (Boundary == ISOTHERMAL ) ||
9504  (Boundary == NEARFIELD_BOUNDARY)) {
9505  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
9506 
9507  Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
9508 
9509  HeatFlux = solver_container->GetHeatFlux(iMarker, iVertex);
9510  HeatFluxTarget = solver_container->GetHeatFluxTarget(iMarker, iVertex);
9511 
9512  Area = 0.0;
9513  for (iDim = 0; iDim < geometry->GetnDim(); iDim++)
9514  Area += Normal[iDim]*Normal[iDim];
9515  Area = sqrt(Area);
9516 
9517  HeatFluxDiff += Area * (HeatFluxTarget - HeatFlux) * (HeatFluxTarget - HeatFlux);
9518 
9519  }
9520 
9521  }
9522  }
9523 
9524 #ifdef HAVE_MPI
9525  su2double MyHeatFluxDiff = HeatFluxDiff; HeatFluxDiff = 0.0;
9526  SU2_MPI::Allreduce(&MyHeatFluxDiff, &HeatFluxDiff, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
9527 #endif
9528 
9529  /*--- Update the total HeatFlux difference coeffient ---*/
9530 
9531  solver_container->SetTotal_HeatFluxDiff(HeatFluxDiff);
9532 
9533  delete [] Point2Vertex;
9534  delete [] PointInDomain;
9535 
9536 }
9537 
9538 void COutput::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry, CConfig *config, bool output) {
9539 
9540  ofstream EquivArea_file, FuncGrad_file;
9541  unsigned short iMarker = 0, iDim;
9542  short *AzimuthalAngle = NULL;
9543  su2double Gamma, auxXCoord, auxYCoord, auxZCoord, InverseDesign = 0.0, DeltaX, Coord_i, Coord_j, jp1Coord, *Coord = NULL, MeanFuntion,
9544  *Face_Normal = NULL, auxArea, auxPress, Mach, Beta, R_Plane, Pressure_Inf,
9545  ModVelocity_Inf, Velocity_Inf[3], factor, *Xcoord = NULL, *Ycoord = NULL, *Zcoord = NULL,
9546  *Pressure = NULL, *FaceArea = NULL, *EquivArea = NULL, *TargetArea = NULL, *NearFieldWeight = NULL,
9547  *Weight = NULL, jFunction, jp1Function;
9548  unsigned long jVertex, iVertex, iPoint, nVertex_NearField = 0, auxPoint,
9549  *IdPoint = NULL, *IdDomain = NULL, auxDomain;
9550  unsigned short iPhiAngle;
9551  ofstream NearFieldEA_file; ifstream TargetEA_file;
9552 
9553  su2double XCoordBegin_OF = config->GetEA_IntLimit(0);
9554  su2double XCoordEnd_OF = config->GetEA_IntLimit(1);
9555 
9556  unsigned short nDim = geometry->GetnDim();
9557  su2double AoA = -(config->GetAoA()*PI_NUMBER/180.0);
9558  su2double EAScaleFactor = config->GetEA_ScaleFactor(); // The EA Obj. Func. should be ~ force based Obj. Func.
9559 
9560  Mach = config->GetMach();
9561  Gamma = config->GetGamma();
9562  Beta = sqrt(Mach*Mach-1.0);
9563  R_Plane = fabs(config->GetEA_IntLimit(2));
9564  Pressure_Inf = config->GetPressure_FreeStreamND();
9565  Velocity_Inf[0] = config->GetVelocity_FreeStreamND()[0];
9566  Velocity_Inf[1] = config->GetVelocity_FreeStreamND()[1];
9567  Velocity_Inf[2] = config->GetVelocity_FreeStreamND()[2];
9568  ModVelocity_Inf = 0;
9569  for (iDim = 0; iDim < 3; iDim++)
9570  ModVelocity_Inf += Velocity_Inf[iDim] * Velocity_Inf[iDim];
9571 
9572  factor = 4.0*sqrt(2.0*Beta*R_Plane) / (Gamma*Pressure_Inf*Mach*Mach);
9573 
9574  if (rank == MASTER_NODE) cout << endl << "Writing Equivalent Area files.";
9575 
9576 #ifndef HAVE_MPI
9577 
9578  /*--- Compute the total number of points on the near-field ---*/
9579 
9580  nVertex_NearField = 0;
9581  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
9582  if (config->GetMarker_All_KindBC(iMarker) == NEARFIELD_BOUNDARY)
9583  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
9584  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
9585  Face_Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
9586  Coord = geometry->node[iPoint]->GetCoord();
9587 
9588  /*--- Using Face_Normal(z), and Coord(z) we identify only a surface,
9589  note that there are 2 NEARFIELD_BOUNDARY surfaces ---*/
9590 
9591  if ((Face_Normal[nDim-1] > 0.0) && (Coord[nDim-1] < 0.0)) nVertex_NearField ++;
9592  }
9593 
9594  /*--- Create an array with all the coordinates, points, pressures, face area,
9595  equivalent area, and nearfield weight ---*/
9596 
9597  Xcoord = new su2double[nVertex_NearField];
9598  Ycoord = new su2double[nVertex_NearField];
9599  Zcoord = new su2double[nVertex_NearField];
9600  AzimuthalAngle = new short[nVertex_NearField];
9601  IdPoint = new unsigned long[nVertex_NearField];
9602  IdDomain = new unsigned long[nVertex_NearField];
9603  Pressure = new su2double[nVertex_NearField];
9604  FaceArea = new su2double[nVertex_NearField];
9605  EquivArea = new su2double[nVertex_NearField];
9606  TargetArea = new su2double[nVertex_NearField];
9607  NearFieldWeight = new su2double[nVertex_NearField];
9608  Weight = new su2double[nVertex_NearField];
9609 
9610  /*--- Copy the boundary information to an array ---*/
9611 
9612  nVertex_NearField = 0;
9613  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
9614  if (config->GetMarker_All_KindBC(iMarker) == NEARFIELD_BOUNDARY)
9615  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
9616  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
9617  Face_Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
9618  Coord = geometry->node[iPoint]->GetCoord();
9619 
9620  if ((Face_Normal[nDim-1] > 0.0) && (Coord[nDim-1] < 0.0)) {
9621 
9622  IdPoint[nVertex_NearField] = iPoint;
9623  Xcoord[nVertex_NearField] = geometry->node[iPoint]->GetCoord(0);
9624  Ycoord[nVertex_NearField] = geometry->node[iPoint]->GetCoord(1);
9625 
9626  if (nDim ==2) {
9627  AzimuthalAngle[nVertex_NearField] = 0;
9628  }
9629 
9630  if (nDim == 3) {
9631  Zcoord[nVertex_NearField] = geometry->node[iPoint]->GetCoord(2);
9632 
9633  /*--- Rotate the nearfield cylinder (AoA) only 3D ---*/
9634 
9635  su2double YcoordRot = Ycoord[nVertex_NearField];
9636  su2double ZcoordRot = Xcoord[nVertex_NearField]*sin(AoA) + Zcoord[nVertex_NearField]*cos(AoA);
9637 
9638  /*--- Compute the Azimuthal angle (resolution of degress in the Azimuthal angle)---*/
9639 
9640  su2double AngleDouble; short AngleInt;
9641  AngleDouble = fabs(atan(-YcoordRot/ZcoordRot)*180.0/PI_NUMBER);
9642 
9643  /*--- Fix an azimuthal line due to misalignments of the near-field ---*/
9644 
9645  su2double FixAzimuthalLine = config->GetFixAzimuthalLine();
9646 
9647  if ((AngleDouble >= FixAzimuthalLine - 0.1) && (AngleDouble <= FixAzimuthalLine + 0.1)) AngleDouble = FixAzimuthalLine - 0.1;
9648 
9649  AngleInt = SU2_TYPE::Short(floor(AngleDouble + 0.5));
9650  if (AngleInt >= 0) AzimuthalAngle[nVertex_NearField] = AngleInt;
9651  else AzimuthalAngle[nVertex_NearField] = 180 + AngleInt;
9652  }
9653 
9654  if (AzimuthalAngle[nVertex_NearField] <= 60) {
9655  Pressure[nVertex_NearField] = solver->node[iPoint]->GetPressure();
9656  FaceArea[nVertex_NearField] = fabs(Face_Normal[nDim-1]);
9657  nVertex_NearField ++;
9658  }
9659 
9660  }
9661  }
9662 
9663 #else
9664 
9665  int nProcessor;
9666  SU2_MPI::Comm_size(MPI_COMM_WORLD, &nProcessor);
9667 
9668  unsigned long nLocalVertex_NearField = 0, MaxLocalVertex_NearField = 0;
9669  int iProcessor;
9670 
9671  unsigned long *Buffer_Receive_nVertex = NULL;
9672  if (rank == MASTER_NODE) {
9673  Buffer_Receive_nVertex = new unsigned long [nProcessor];
9674  }
9675 
9676  /*--- Compute the total number of points of the near-field ghost nodes ---*/
9677 
9678  nLocalVertex_NearField = 0;
9679  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
9680  if (config->GetMarker_All_KindBC(iMarker) == NEARFIELD_BOUNDARY)
9681  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
9682  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
9683  Face_Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
9684  Coord = geometry->node[iPoint]->GetCoord();
9685 
9686  if (geometry->node[iPoint]->GetDomain())
9687  if ((Face_Normal[nDim-1] > 0.0) && (Coord[nDim-1] < 0.0))
9688  nLocalVertex_NearField ++;
9689  }
9690 
9691  unsigned long *Buffer_Send_nVertex = new unsigned long [1];
9692  Buffer_Send_nVertex[0] = nLocalVertex_NearField;
9693 
9694  /*--- Send Near-Field vertex information --*/
9695 
9696  SU2_MPI::Allreduce(&nLocalVertex_NearField, &nVertex_NearField, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
9697  SU2_MPI::Allreduce(&nLocalVertex_NearField, &MaxLocalVertex_NearField, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
9698  SU2_MPI::Gather(Buffer_Send_nVertex, 1, MPI_UNSIGNED_LONG, Buffer_Receive_nVertex, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
9699  delete [] Buffer_Send_nVertex;
9700 
9701  su2double *Buffer_Send_Xcoord = new su2double[MaxLocalVertex_NearField];
9702  su2double *Buffer_Send_Ycoord = new su2double[MaxLocalVertex_NearField];
9703  su2double *Buffer_Send_Zcoord = new su2double[MaxLocalVertex_NearField];
9704  unsigned long *Buffer_Send_IdPoint = new unsigned long [MaxLocalVertex_NearField];
9705  su2double *Buffer_Send_Pressure = new su2double [MaxLocalVertex_NearField];
9706  su2double *Buffer_Send_FaceArea = new su2double[MaxLocalVertex_NearField];
9707 
9708  su2double *Buffer_Receive_Xcoord = NULL;
9709  su2double *Buffer_Receive_Ycoord = NULL;
9710  su2double *Buffer_Receive_Zcoord = NULL;
9711  unsigned long *Buffer_Receive_IdPoint = NULL;
9712  su2double *Buffer_Receive_Pressure = NULL;
9713  su2double *Buffer_Receive_FaceArea = NULL;
9714 
9715  if (rank == MASTER_NODE) {
9716  Buffer_Receive_Xcoord = new su2double[nProcessor*MaxLocalVertex_NearField];
9717  Buffer_Receive_Ycoord = new su2double[nProcessor*MaxLocalVertex_NearField];
9718  Buffer_Receive_Zcoord = new su2double[nProcessor*MaxLocalVertex_NearField];
9719  Buffer_Receive_IdPoint = new unsigned long[nProcessor*MaxLocalVertex_NearField];
9720  Buffer_Receive_Pressure = new su2double[nProcessor*MaxLocalVertex_NearField];
9721  Buffer_Receive_FaceArea = new su2double[nProcessor*MaxLocalVertex_NearField];
9722  }
9723 
9724  unsigned long nBuffer_Xcoord = MaxLocalVertex_NearField;
9725  unsigned long nBuffer_Ycoord = MaxLocalVertex_NearField;
9726  unsigned long nBuffer_Zcoord = MaxLocalVertex_NearField;
9727  unsigned long nBuffer_IdPoint = MaxLocalVertex_NearField;
9728  unsigned long nBuffer_Pressure = MaxLocalVertex_NearField;
9729  unsigned long nBuffer_FaceArea = MaxLocalVertex_NearField;
9730 
9731  for (iVertex = 0; iVertex < MaxLocalVertex_NearField; iVertex++) {
9732  Buffer_Send_IdPoint[iVertex] = 0; Buffer_Send_Pressure[iVertex] = 0.0;
9733  Buffer_Send_FaceArea[iVertex] = 0.0; Buffer_Send_Xcoord[iVertex] = 0.0;
9734  Buffer_Send_Ycoord[iVertex] = 0.0; Buffer_Send_Zcoord[iVertex] = 0.0;
9735  }
9736 
9737  /*--- Copy coordinates, index points, and pressures to the auxiliar vector --*/
9738 
9739  nLocalVertex_NearField = 0;
9740  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
9741  if (config->GetMarker_All_KindBC(iMarker) == NEARFIELD_BOUNDARY)
9742  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
9743  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
9744  Face_Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
9745  Coord = geometry->node[iPoint]->GetCoord();
9746 
9747  if (geometry->node[iPoint]->GetDomain())
9748  if ((Face_Normal[nDim-1] > 0.0) && (Coord[nDim-1] < 0.0)) {
9749  Buffer_Send_IdPoint[nLocalVertex_NearField] = iPoint;
9750  Buffer_Send_Xcoord[nLocalVertex_NearField] = geometry->node[iPoint]->GetCoord(0);
9751  Buffer_Send_Ycoord[nLocalVertex_NearField] = geometry->node[iPoint]->GetCoord(1);
9752  Buffer_Send_Zcoord[nLocalVertex_NearField] = geometry->node[iPoint]->GetCoord(2);
9753  Buffer_Send_Pressure[nLocalVertex_NearField] = solver->node[iPoint]->GetPressure();
9754  Buffer_Send_FaceArea[nLocalVertex_NearField] = fabs(Face_Normal[nDim-1]);
9755  nLocalVertex_NearField++;
9756  }
9757  }
9758 
9759  /*--- Send all the information --*/
9760 
9761  SU2_MPI::Gather(Buffer_Send_Xcoord, nBuffer_Xcoord, MPI_DOUBLE, Buffer_Receive_Xcoord, nBuffer_Xcoord, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
9762  SU2_MPI::Gather(Buffer_Send_Ycoord, nBuffer_Ycoord, MPI_DOUBLE, Buffer_Receive_Ycoord, nBuffer_Ycoord, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
9763  SU2_MPI::Gather(Buffer_Send_Zcoord, nBuffer_Zcoord, MPI_DOUBLE, Buffer_Receive_Zcoord, nBuffer_Zcoord, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
9764  SU2_MPI::Gather(Buffer_Send_IdPoint, nBuffer_IdPoint, MPI_UNSIGNED_LONG, Buffer_Receive_IdPoint, nBuffer_IdPoint, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
9765  SU2_MPI::Gather(Buffer_Send_Pressure, nBuffer_Pressure, MPI_DOUBLE, Buffer_Receive_Pressure, nBuffer_Pressure, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
9766  SU2_MPI::Gather(Buffer_Send_FaceArea, nBuffer_FaceArea, MPI_DOUBLE, Buffer_Receive_FaceArea, nBuffer_FaceArea, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
9767  delete [] Buffer_Send_Xcoord;
9768  delete [] Buffer_Send_Ycoord;
9769  delete [] Buffer_Send_Zcoord;
9770  delete [] Buffer_Send_IdPoint;
9771  delete [] Buffer_Send_Pressure;
9772  delete [] Buffer_Send_FaceArea;
9773 
9774  if (rank == MASTER_NODE) {
9775 
9776  Xcoord = new su2double[nVertex_NearField];
9777  Ycoord = new su2double[nVertex_NearField];
9778  Zcoord = new su2double[nVertex_NearField];
9779  AzimuthalAngle = new short[nVertex_NearField];
9780  IdPoint = new unsigned long[nVertex_NearField];
9781  IdDomain = new unsigned long[nVertex_NearField];
9782  Pressure = new su2double[nVertex_NearField];
9783  FaceArea = new su2double[nVertex_NearField];
9784  EquivArea = new su2double[nVertex_NearField];
9785  TargetArea = new su2double[nVertex_NearField];
9786  NearFieldWeight = new su2double[nVertex_NearField];
9787  Weight = new su2double[nVertex_NearField];
9788 
9789  nVertex_NearField = 0;
9790  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++)
9791  for (iVertex = 0; iVertex < Buffer_Receive_nVertex[iProcessor]; iVertex++) {
9792  Xcoord[nVertex_NearField] = Buffer_Receive_Xcoord[iProcessor*MaxLocalVertex_NearField+iVertex];
9793  Ycoord[nVertex_NearField] = Buffer_Receive_Ycoord[iProcessor*MaxLocalVertex_NearField+iVertex];
9794 
9795  if (nDim == 2) {
9796  AzimuthalAngle[nVertex_NearField] = 0;
9797  }
9798 
9799  if (nDim == 3) {
9800  Zcoord[nVertex_NearField] = Buffer_Receive_Zcoord[iProcessor*MaxLocalVertex_NearField+iVertex];
9801 
9802  /*--- Rotate the nearfield cylinder ---*/
9803 
9804  su2double YcoordRot = Ycoord[nVertex_NearField];
9805  su2double ZcoordRot = Xcoord[nVertex_NearField]*sin(AoA) + Zcoord[nVertex_NearField]*cos(AoA);
9806 
9807  /*--- Compute the Azimuthal angle ---*/
9808 
9809  su2double AngleDouble; short AngleInt;
9810  AngleDouble = fabs(atan(-YcoordRot/ZcoordRot)*180.0/PI_NUMBER);
9811 
9812  /*--- Fix an azimuthal line due to misalignments of the near-field ---*/
9813 
9814  su2double FixAzimuthalLine = config->GetFixAzimuthalLine();
9815 
9816  if ((AngleDouble >= FixAzimuthalLine - 0.1) && (AngleDouble <= FixAzimuthalLine + 0.1))
9817  AngleDouble = FixAzimuthalLine - 0.1;
9818 
9819  AngleInt = SU2_TYPE::Short(floor(AngleDouble + 0.5));
9820 
9821  if (AngleInt >= 0) AzimuthalAngle[nVertex_NearField] = AngleInt;
9822  else AzimuthalAngle[nVertex_NearField] = 180 + AngleInt;
9823  }
9824 
9825  if (AzimuthalAngle[nVertex_NearField] <= 60) {
9826  IdPoint[nVertex_NearField] = Buffer_Receive_IdPoint[iProcessor*MaxLocalVertex_NearField+iVertex];
9827  Pressure[nVertex_NearField] = Buffer_Receive_Pressure[iProcessor*MaxLocalVertex_NearField+iVertex];
9828  FaceArea[nVertex_NearField] = Buffer_Receive_FaceArea[iProcessor*MaxLocalVertex_NearField+iVertex];
9829  IdDomain[nVertex_NearField] = iProcessor;
9830  nVertex_NearField++;
9831  }
9832 
9833  }
9834 
9835  delete [] Buffer_Receive_nVertex;
9836 
9837  delete [] Buffer_Receive_Xcoord;
9838  delete [] Buffer_Receive_Ycoord;
9839  delete [] Buffer_Receive_Zcoord;
9840  delete [] Buffer_Receive_IdPoint;
9841  delete [] Buffer_Receive_Pressure;
9842  delete [] Buffer_Receive_FaceArea;
9843 
9844  }
9845 
9846 #endif
9847 
9848  if (rank == MASTER_NODE) {
9849 
9850  vector<short> PhiAngleList;
9851  vector<short>::iterator IterPhiAngleList;
9852 
9853  for (iVertex = 0; iVertex < nVertex_NearField; iVertex++)
9854  PhiAngleList.push_back(AzimuthalAngle[iVertex]);
9855 
9856  sort( PhiAngleList.begin(), PhiAngleList.end());
9857  IterPhiAngleList = unique( PhiAngleList.begin(), PhiAngleList.end());
9858  PhiAngleList.resize( IterPhiAngleList - PhiAngleList.begin() );
9859 
9860  /*--- Create vectors and distribute the values among the different PhiAngle queues ---*/
9861 
9862  vector<vector<su2double> > Xcoord_PhiAngle; Xcoord_PhiAngle.resize(PhiAngleList.size());
9863  vector<vector<su2double> > Ycoord_PhiAngle; Ycoord_PhiAngle.resize(PhiAngleList.size());
9864  vector<vector<su2double> > Zcoord_PhiAngle; Zcoord_PhiAngle.resize(PhiAngleList.size());
9865  vector<vector<unsigned long> > IdPoint_PhiAngle; IdPoint_PhiAngle.resize(PhiAngleList.size());
9866  vector<vector<unsigned long> > IdDomain_PhiAngle; IdDomain_PhiAngle.resize(PhiAngleList.size());
9867  vector<vector<su2double> > Pressure_PhiAngle; Pressure_PhiAngle.resize(PhiAngleList.size());
9868  vector<vector<su2double> > FaceArea_PhiAngle; FaceArea_PhiAngle.resize(PhiAngleList.size());
9869  vector<vector<su2double> > EquivArea_PhiAngle; EquivArea_PhiAngle.resize(PhiAngleList.size());
9870  vector<vector<su2double> > TargetArea_PhiAngle; TargetArea_PhiAngle.resize(PhiAngleList.size());
9871  vector<vector<su2double> > NearFieldWeight_PhiAngle; NearFieldWeight_PhiAngle.resize(PhiAngleList.size());
9872  vector<vector<su2double> > Weight_PhiAngle; Weight_PhiAngle.resize(PhiAngleList.size());
9873 
9874  /*--- Distribute the values among the different PhiAngles ---*/
9875 
9876  for (iVertex = 0; iVertex < nVertex_NearField; iVertex++)
9877  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++)
9878  if (AzimuthalAngle[iVertex] == PhiAngleList[iPhiAngle]) {
9879  Xcoord_PhiAngle[iPhiAngle].push_back(Xcoord[iVertex]);
9880  Ycoord_PhiAngle[iPhiAngle].push_back(Ycoord[iVertex]);
9881  Zcoord_PhiAngle[iPhiAngle].push_back(Zcoord[iVertex]);
9882  IdPoint_PhiAngle[iPhiAngle].push_back(IdPoint[iVertex]);
9883  IdDomain_PhiAngle[iPhiAngle].push_back(IdDomain[iVertex]);
9884  Pressure_PhiAngle[iPhiAngle].push_back(Pressure[iVertex]);
9885  FaceArea_PhiAngle[iPhiAngle].push_back(FaceArea[iVertex]);
9886  EquivArea_PhiAngle[iPhiAngle].push_back(EquivArea[iVertex]);
9887  TargetArea_PhiAngle[iPhiAngle].push_back(TargetArea[iVertex]);
9888  NearFieldWeight_PhiAngle[iPhiAngle].push_back(NearFieldWeight[iVertex]);
9889  Weight_PhiAngle[iPhiAngle].push_back(Weight[iVertex]);
9890  }
9891 
9892  /*--- Order the arrays (x Coordinate, Pressure, Point, and Domain) ---*/
9893 
9894  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++)
9895  for (iVertex = 0; iVertex < Xcoord_PhiAngle[iPhiAngle].size(); iVertex++)
9896  for (jVertex = 0; jVertex < Xcoord_PhiAngle[iPhiAngle].size() - 1 - iVertex; jVertex++)
9897  if (Xcoord_PhiAngle[iPhiAngle][jVertex] > Xcoord_PhiAngle[iPhiAngle][jVertex+1]) {
9898  auxXCoord = Xcoord_PhiAngle[iPhiAngle][jVertex]; Xcoord_PhiAngle[iPhiAngle][jVertex] = Xcoord_PhiAngle[iPhiAngle][jVertex+1]; Xcoord_PhiAngle[iPhiAngle][jVertex+1] = auxXCoord;
9899  auxYCoord = Ycoord_PhiAngle[iPhiAngle][jVertex]; Ycoord_PhiAngle[iPhiAngle][jVertex] = Ycoord_PhiAngle[iPhiAngle][jVertex+1]; Ycoord_PhiAngle[iPhiAngle][jVertex+1] = auxYCoord;
9900  auxZCoord = Zcoord_PhiAngle[iPhiAngle][jVertex]; Zcoord_PhiAngle[iPhiAngle][jVertex] = Zcoord_PhiAngle[iPhiAngle][jVertex+1]; Zcoord_PhiAngle[iPhiAngle][jVertex+1] = auxZCoord;
9901  auxPress = Pressure_PhiAngle[iPhiAngle][jVertex]; Pressure_PhiAngle[iPhiAngle][jVertex] = Pressure_PhiAngle[iPhiAngle][jVertex+1]; Pressure_PhiAngle[iPhiAngle][jVertex+1] = auxPress;
9902  auxArea = FaceArea_PhiAngle[iPhiAngle][jVertex]; FaceArea_PhiAngle[iPhiAngle][jVertex] = FaceArea_PhiAngle[iPhiAngle][jVertex+1]; FaceArea_PhiAngle[iPhiAngle][jVertex+1] = auxArea;
9903  auxPoint = IdPoint_PhiAngle[iPhiAngle][jVertex]; IdPoint_PhiAngle[iPhiAngle][jVertex] = IdPoint_PhiAngle[iPhiAngle][jVertex+1]; IdPoint_PhiAngle[iPhiAngle][jVertex+1] = auxPoint;
9904  auxDomain = IdDomain_PhiAngle[iPhiAngle][jVertex]; IdDomain_PhiAngle[iPhiAngle][jVertex] = IdDomain_PhiAngle[iPhiAngle][jVertex+1]; IdDomain_PhiAngle[iPhiAngle][jVertex+1] = auxDomain;
9905  }
9906 
9907 
9908  /*--- Check that all the azimuth lists have the same size ---*/
9909 
9910  unsigned short nVertex = Xcoord_PhiAngle[0].size();
9911  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) {
9912  unsigned short nVertex_aux = Xcoord_PhiAngle[iPhiAngle].size();
9913  if (nVertex_aux != nVertex) cout <<"Be careful!!! one azimuth list is shorter than the other"<< endl;
9914  nVertex = min(nVertex, nVertex_aux);
9915  }
9916 
9917  /*--- Compute equivalent area distribution at each azimuth angle ---*/
9918 
9919  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) {
9920  EquivArea_PhiAngle[iPhiAngle][0] = 0.0;
9921  for (iVertex = 1; iVertex < EquivArea_PhiAngle[iPhiAngle].size(); iVertex++) {
9922  EquivArea_PhiAngle[iPhiAngle][iVertex] = 0.0;
9923 
9924  Coord_i = Xcoord_PhiAngle[iPhiAngle][iVertex]*cos(AoA) - Zcoord_PhiAngle[iPhiAngle][iVertex]*sin(AoA);
9925 
9926  for (jVertex = 0; jVertex < iVertex-1; jVertex++) {
9927 
9928  Coord_j = Xcoord_PhiAngle[iPhiAngle][jVertex]*cos(AoA) - Zcoord_PhiAngle[iPhiAngle][jVertex]*sin(AoA);
9929  jp1Coord = Xcoord_PhiAngle[iPhiAngle][jVertex+1]*cos(AoA) - Zcoord_PhiAngle[iPhiAngle][jVertex+1]*sin(AoA);
9930 
9931  jFunction = factor*(Pressure_PhiAngle[iPhiAngle][jVertex] - Pressure_Inf)*sqrt(Coord_i-Coord_j);
9932  jp1Function = factor*(Pressure_PhiAngle[iPhiAngle][jVertex+1] - Pressure_Inf)*sqrt(Coord_i-jp1Coord);
9933 
9934  DeltaX = (jp1Coord-Coord_j);
9935  MeanFuntion = 0.5*(jp1Function + jFunction);
9936  EquivArea_PhiAngle[iPhiAngle][iVertex] += DeltaX * MeanFuntion;
9937  }
9938  }
9939  }
9940 
9941  /*--- Create a file with the equivalent area distribution at each azimuthal angle ---*/
9942 
9943  NearFieldEA_file.precision(15);
9944 
9945  if (output) {
9946 
9947  NearFieldEA_file.open("Equivalent_Area.dat", ios::out);
9948  NearFieldEA_file << "TITLE = \"Equivalent Area evaluation at each azimuthal angle\"" << "\n";
9949 
9950  if (config->GetSystemMeasurements() == US)
9951  NearFieldEA_file << "VARIABLES = \"Height (in) at r="<< R_Plane*12.0 << " in. (cyl. coord. system)\"";
9952  else
9953  NearFieldEA_file << "VARIABLES = \"Height (m) at r="<< R_Plane << " m. (cylindrical coordinate system)\"";
9954 
9955  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) {
9956  if (config->GetSystemMeasurements() == US)
9957  NearFieldEA_file << ", \"Equivalent Area (ft<sup>2</sup>), <greek>F</greek>= " << PhiAngleList[iPhiAngle] << " deg.\"";
9958  else
9959  NearFieldEA_file << ", \"Equivalent Area (m<sup>2</sup>), <greek>F</greek>= " << PhiAngleList[iPhiAngle] << " deg.\"";
9960  }
9961 
9962  NearFieldEA_file << "\n";
9963  for (iVertex = 0; iVertex < EquivArea_PhiAngle[0].size(); iVertex++) {
9964 
9965  su2double XcoordRot = Xcoord_PhiAngle[0][iVertex]*cos(AoA) - Zcoord_PhiAngle[0][iVertex]*sin(AoA);
9966  su2double XcoordRot_init = Xcoord_PhiAngle[0][0]*cos(AoA) - Zcoord_PhiAngle[0][0]*sin(AoA);
9967 
9968  if (config->GetSystemMeasurements() == US)
9969  NearFieldEA_file << scientific << (XcoordRot - XcoordRot_init) * 12.0;
9970  else
9971  NearFieldEA_file << scientific << (XcoordRot - XcoordRot_init);
9972 
9973  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) {
9974  NearFieldEA_file << scientific << ", " << EquivArea_PhiAngle[iPhiAngle][iVertex];
9975  }
9976 
9977  NearFieldEA_file << "\n";
9978 
9979  }
9980  NearFieldEA_file.close();
9981 
9982  }
9983 
9984  /*--- Read target equivalent area from the configuration file,
9985  this first implementation requires a complete table (same as the original
9986  EA table). so... no interpolation. ---*/
9987 
9988  vector<vector<su2double> > TargetArea_PhiAngle_Trans;
9989  TargetEA_file.open("TargetEA.dat", ios::in);
9990 
9991  if (TargetEA_file.fail()) {
9992  /*--- Set the table to 0 ---*/
9993  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++)
9994  for (iVertex = 0; iVertex < TargetArea_PhiAngle[iPhiAngle].size(); iVertex++)
9995  TargetArea_PhiAngle[iPhiAngle][iVertex] = 0.0;
9996  }
9997  else {
9998 
9999  /*--- skip header lines ---*/
10000 
10001  string line;
10002  getline(TargetEA_file, line);
10003  getline(TargetEA_file, line);
10004 
10005  while (TargetEA_file) {
10006 
10007  string line;
10008  getline(TargetEA_file, line);
10009  istringstream is(line);
10010  vector<su2double> row;
10011  unsigned short iter = 0;
10012 
10013  while (is.good()) {
10014  string token;
10015  getline(is, token,',');
10016 
10017  istringstream js(token);
10018 
10019  su2double data;
10020  js >> data;
10021 
10022  /*--- The first element in the table is the coordinate (in or m)---*/
10023 
10024  if (iter != 0) row.push_back(data);
10025  iter++;
10026 
10027  }
10028  TargetArea_PhiAngle_Trans.push_back(row);
10029  }
10030 
10031  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++)
10032  for (iVertex = 0; iVertex < EquivArea_PhiAngle[iPhiAngle].size(); iVertex++)
10033  TargetArea_PhiAngle[iPhiAngle][iVertex] = TargetArea_PhiAngle_Trans[iVertex][iPhiAngle];
10034 
10035  }
10036 
10037  /*--- Divide by the number of Phi angles in the nearfield ---*/
10038 
10039  su2double PhiFactor = 1.0/su2double(PhiAngleList.size());
10040 
10041  /*--- Evaluate the objective function ---*/
10042 
10043  InverseDesign = 0;
10044  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++)
10045  for (iVertex = 0; iVertex < EquivArea_PhiAngle[iPhiAngle].size(); iVertex++) {
10046  Weight_PhiAngle[iPhiAngle][iVertex] = 1.0;
10047  Coord_i = Xcoord_PhiAngle[iPhiAngle][iVertex];
10048 
10049  su2double Difference = EquivArea_PhiAngle[iPhiAngle][iVertex]-TargetArea_PhiAngle[iPhiAngle][iVertex];
10050  su2double percentage = fabs(Difference)*100/fabs(TargetArea_PhiAngle[iPhiAngle][iVertex]);
10051 
10052  if ((percentage < 0.1) || (Coord_i < XCoordBegin_OF) || (Coord_i > XCoordEnd_OF)) Difference = 0.0;
10053 
10054  InverseDesign += EAScaleFactor*PhiFactor*Weight_PhiAngle[iPhiAngle][iVertex]*Difference*Difference;
10055 
10056  }
10057 
10058  /*--- Evaluate the weight of the nearfield pressure (adjoint input) ---*/
10059 
10060  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++)
10061  for (iVertex = 0; iVertex < EquivArea_PhiAngle[iPhiAngle].size(); iVertex++) {
10062  Coord_i = Xcoord_PhiAngle[iPhiAngle][iVertex];
10063  NearFieldWeight_PhiAngle[iPhiAngle][iVertex] = 0.0;
10064  for (jVertex = iVertex; jVertex < EquivArea_PhiAngle[iPhiAngle].size(); jVertex++) {
10065  Coord_j = Xcoord_PhiAngle[iPhiAngle][jVertex];
10066  Weight_PhiAngle[iPhiAngle][iVertex] = 1.0;
10067 
10068  su2double Difference = EquivArea_PhiAngle[iPhiAngle][jVertex]-TargetArea_PhiAngle[iPhiAngle][jVertex];
10069  su2double percentage = fabs(Difference)*100/fabs(TargetArea_PhiAngle[iPhiAngle][jVertex]);
10070 
10071  if ((percentage < 0.1) || (Coord_j < XCoordBegin_OF) || (Coord_j > XCoordEnd_OF)) Difference = 0.0;
10072 
10073  NearFieldWeight_PhiAngle[iPhiAngle][iVertex] += EAScaleFactor*PhiFactor*Weight_PhiAngle[iPhiAngle][iVertex]*2.0*Difference*factor*sqrt(Coord_j-Coord_i);
10074  }
10075  }
10076 
10077  /*--- Write the Nearfield pressure at each Azimuthal PhiAngle ---*/
10078 
10079  EquivArea_file.precision(15);
10080 
10081  if (output) {
10082 
10083  EquivArea_file.open("nearfield_flow.dat", ios::out);
10084  EquivArea_file << "TITLE = \"Equivalent Area evaluation at each azimuthal angle\"" << "\n";
10085 
10086  if (config->GetSystemMeasurements() == US)
10087  EquivArea_file << "VARIABLES = \"Height (in) at r="<< R_Plane*12.0 << " in. (cyl. coord. system)\",\"Equivalent Area (ft<sup>2</sup>)\",\"Target Equivalent Area (ft<sup>2</sup>)\",\"Cp\"" << "\n";
10088  else
10089  EquivArea_file << "VARIABLES = \"Height (m) at r="<< R_Plane << " m. (cylindrical coordinate system)\",\"Equivalent Area (m<sup>2</sup>)\",\"Target Equivalent Area (m<sup>2</sup>)\",\"Cp\"" << "\n";
10090 
10091  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) {
10092  EquivArea_file << fixed << "ZONE T= \"<greek>F</greek>=" << PhiAngleList[iPhiAngle] << " deg.\"" << "\n";
10093  for (iVertex = 0; iVertex < Xcoord_PhiAngle[iPhiAngle].size(); iVertex++) {
10094 
10095  su2double XcoordRot = Xcoord_PhiAngle[0][iVertex]*cos(AoA) - Zcoord_PhiAngle[0][iVertex]*sin(AoA);
10096  su2double XcoordRot_init = Xcoord_PhiAngle[0][0]*cos(AoA) - Zcoord_PhiAngle[0][0]*sin(AoA);
10097 
10098  if (config->GetSystemMeasurements() == US)
10099  EquivArea_file << scientific << (XcoordRot - XcoordRot_init) * 12.0;
10100  else
10101  EquivArea_file << scientific << (XcoordRot - XcoordRot_init);
10102 
10103  EquivArea_file << scientific << ", " << EquivArea_PhiAngle[iPhiAngle][iVertex]
10104  << ", " << TargetArea_PhiAngle[iPhiAngle][iVertex] << ", " << (Pressure_PhiAngle[iPhiAngle][iVertex]-Pressure_Inf)/Pressure_Inf << "\n";
10105  }
10106  }
10107 
10108  EquivArea_file.close();
10109 
10110  }
10111 
10112  /*--- Write Weight file for adjoint computation ---*/
10113 
10114  FuncGrad_file.precision(15);
10115 
10116  if (output) {
10117 
10118  FuncGrad_file.open("WeightNF.dat", ios::out);
10119 
10120  FuncGrad_file << scientific << "-1.0";
10121  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++)
10122  FuncGrad_file << scientific << "\t" << PhiAngleList[iPhiAngle];
10123  FuncGrad_file << "\n";
10124 
10125  for (iVertex = 0; iVertex < NearFieldWeight_PhiAngle[0].size(); iVertex++) {
10126  su2double XcoordRot = Xcoord_PhiAngle[0][iVertex]*cos(AoA) - Zcoord_PhiAngle[0][iVertex]*sin(AoA);
10127  FuncGrad_file << scientific << XcoordRot;
10128  for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++)
10129  FuncGrad_file << scientific << "\t" << NearFieldWeight_PhiAngle[iPhiAngle][iVertex];
10130  FuncGrad_file << "\n";
10131  }
10132  FuncGrad_file.close();
10133 
10134  }
10135 
10136  /*--- Delete structures ---*/
10137 
10138  delete [] Xcoord; delete [] Ycoord; delete [] Zcoord;
10139  delete [] AzimuthalAngle; delete [] IdPoint; delete [] IdDomain;
10140  delete [] Pressure; delete [] FaceArea;
10141  delete [] EquivArea; delete [] TargetArea;
10142  delete [] NearFieldWeight; delete [] Weight;
10143 
10144  }
10145 
10146 #ifndef HAVE_MPI
10147 
10148  /*--- Store the value of the NearField coefficient ---*/
10149 
10150  solver->SetTotal_CEquivArea(InverseDesign);
10151 
10152 #else
10153 
10154  /*--- Send the value of the NearField coefficient to all the processors ---*/
10155 
10156  SU2_MPI::Bcast(&InverseDesign, 1, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10157 
10158  /*--- Store the value of the NearField coefficient ---*/
10159 
10160  solver->SetTotal_CEquivArea(InverseDesign);
10161 
10162 #endif
10163 
10164 }
10165 
10166 void COutput::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometry, CConfig *config, bool output) {
10167 
10168  unsigned short iMarker, iDim, iMarker_Analyze;
10169  unsigned long iPoint, iVertex;
10170  su2double xCoord = 0.0, yCoord = 0.0, zCoord = 0.0, Area = 0.0, *Vector, TotalArea = 0.0;
10171  su2double xCoord_CG = 0.0, yCoord_CG = 0.0, zCoord_CG = 0.0, TipRadius, HubRadius, Distance = 0.0, Distance_Mirror = 0.0;
10172  su2double *r, MinDistance, xCoord_ = 0.0, yCoord_ = 0.0, zCoord_ = 0;
10173  unsigned short iStation, iAngle, nAngle;
10174  char cstr[200];
10175  su2double *** ProbeArray, dx = 0.0, dy = 0.0, dz = 0.0, dx_ = 0.0, dy_ = 0.0, dz_ = 0.0, UpVector[3], radians, RotatedVector[3];
10176  su2double Pressure, SoundSpeed, Velocity2, Mach, Gamma, TotalPressure, Mach_Inf, TotalPressure_Inf,
10177  Temperature, TotalTemperature, Pressure_Inf, Temperature_Inf, TotalTemperature_Inf, Velocity_Inf, Density;
10178  unsigned short nDim = geometry->GetnDim();
10179  unsigned short Theta, nStation;
10180  unsigned long nVertex_Surface, nLocalVertex_Surface, MaxLocalVertex_Surface;
10181  unsigned long Buffer_Send_nVertex[1], *Buffer_Recv_nVertex = NULL;
10182  unsigned long Total_Index;
10183  unsigned short Theta_DC60 = 60, nStation_DC60 = 5;
10184  su2double PT_Mean, Mach_Mean, q_Mean, PT, q, *PT_Sector, PT_Sector_Min, DC60, *PT_Station, *PT_Station_Min, *Mach_Station, *Mach_Station_Min, IDR, IDC, IDC_Mach;
10185 
10186 
10187  bool Engine_HalfModel = config->GetEngine_HalfModel();
10188  su2double SignFlip = 1.0;
10189  su2double Beta, Alpha;
10190  su2double Mach_ij, Mach_ip1j, Mach_im1j, Mach_ijp1, Mach_ijm1, Filtered_Mach;
10191  su2double Alpha_ij, Alpha_ip1j, Alpha_im1j, Alpha_ijp1, Alpha_ijm1, Filtered_Alpha;
10192  su2double Beta_ij, Beta_ip1j, Beta_im1j, Beta_ijp1, Beta_ijm1, Filtered_Beta;
10193  su2double a, b, c, d;
10194 
10195  int iProcessor, nProcessor;
10196  nProcessor = size;
10197 
10198 
10199  if (rank == MASTER_NODE && !config->GetDiscrete_Adjoint()) cout << endl << "Writing Surface Analysis file (surface_analysis.dat).";
10200 
10201  /*--- Open and rrite file name with extension if unsteady ---*/
10202 
10203  ofstream SurfFlow_file;
10204 
10205  if (output && (rank == MASTER_NODE)) {
10206 
10207  if ((config->GetOutput_FileFormat() == PARAVIEW) || (config->GetOutput_FileFormat() == PARAVIEW_BINARY)) strcpy (cstr, "surface_analysis.vtk");
10208  else strcpy (cstr, "surface_analysis.dat");
10209 
10210  SurfFlow_file.precision(15);
10211 
10212  SurfFlow_file.open(cstr, ios::out);
10213 
10214  if ((config->GetOutput_FileFormat() == PARAVIEW) || (config->GetOutput_FileFormat() == PARAVIEW_BINARY)) {
10215  SurfFlow_file << "# vtk DataFile Version 3.0" << endl;
10216  SurfFlow_file << "vtk output" << endl;
10217  SurfFlow_file << "ASCII" << endl;
10218  }
10219  else {
10220  SurfFlow_file <<"TITLE = \"Surface Analysis\"" <<endl;
10221  SurfFlow_file <<"VARIABLES = \"y(in)\", \"z(in)\", \"PT/PT<sub>inf</sub>\", \"TT/TT<sub>inf</sub>\", \"P/P<sub>inf</sub>\", \"T/T<sub>inf</sub>\", \"v<sub>x</sub>/v<sub>inf</sub>\", \"v<sub>y</sub>/v<sub>inf</sub>\", \"v<sub>z</sub>/v<sub>inf</sub>\", \"<greek>a</greek> (deg)\", \"<greek>b</greek> (deg)\", \"Mach\", \"Filtered <greek>a</greek> (deg)\", \"Filtered <greek>b</greek> (deg)\", \"Filtered Mach\"" << endl;
10222  }
10223 
10224  }
10225 
10226  /*--- Loop over all the markers to analyze ---*/
10227 
10228  for (iMarker_Analyze = 0; iMarker_Analyze < config->GetnMarker_Analyze(); iMarker_Analyze++) {
10229 
10230  string Analyze_TagBound = config->GetMarker_Analyze_TagBound(iMarker_Analyze);
10231 
10232  nVertex_Surface = 0; nLocalVertex_Surface = 0; MaxLocalVertex_Surface = 0;
10233 
10234  /*--- Find the max number of surface vertices among all
10235  partitions and set up buffers. The master node will handle the
10236  writing of the CSV file after gathering all of the data. ---*/
10237 
10238  nLocalVertex_Surface = 0;
10239  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
10240  string Marker_TagBound = config->GetMarker_All_TagBound(iMarker);
10241  if (Marker_TagBound == Analyze_TagBound) {
10242  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
10243  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
10244  if (geometry->node[iPoint]->GetDomain()) nLocalVertex_Surface++;
10245  }
10246  }
10247  }
10248 
10249  /*--- Communicate the number of local vertices on each partition
10250  to the master node ---*/
10251 
10252  Buffer_Send_nVertex[0] = nLocalVertex_Surface;
10253  if (rank == MASTER_NODE) Buffer_Recv_nVertex = new unsigned long [nProcessor];
10254 
10255 #ifdef HAVE_MPI
10256  SU2_MPI::Allreduce(&nLocalVertex_Surface, &MaxLocalVertex_Surface, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
10257  SU2_MPI::Gather(&Buffer_Send_nVertex, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nVertex, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
10258 #else
10259  MaxLocalVertex_Surface = nLocalVertex_Surface;
10260  Buffer_Recv_nVertex[MASTER_NODE] = Buffer_Send_nVertex[MASTER_NODE];
10261 #endif
10262 
10263  /*--- Send and Recv buffers ---*/
10264 
10265  su2double *Buffer_Send_Coord_x = NULL, *Buffer_Recv_Coord_x = NULL;
10266  Buffer_Send_Coord_x = new su2double [MaxLocalVertex_Surface];
10267 
10268  su2double *Buffer_Send_Coord_y = NULL, *Buffer_Recv_Coord_y = NULL;
10269  Buffer_Send_Coord_y = new su2double [MaxLocalVertex_Surface];
10270 
10271  su2double *Buffer_Send_Coord_z = NULL, *Buffer_Recv_Coord_z = NULL;
10272  if (nDim == 3) Buffer_Send_Coord_z = new su2double [MaxLocalVertex_Surface];
10273 
10274  su2double *Buffer_Send_PT = NULL, *Buffer_Recv_PT = NULL;
10275  Buffer_Send_PT = new su2double [MaxLocalVertex_Surface];
10276 
10277  su2double *Buffer_Send_TT = NULL, *Buffer_Recv_TT = NULL;
10278  Buffer_Send_TT = new su2double [MaxLocalVertex_Surface];
10279 
10280  su2double *Buffer_Send_P = NULL, *Buffer_Recv_P = NULL;
10281  Buffer_Send_P = new su2double [MaxLocalVertex_Surface];
10282 
10283  su2double *Buffer_Send_T = NULL, *Buffer_Recv_T = NULL;
10284  Buffer_Send_T = new su2double [MaxLocalVertex_Surface];
10285 
10286  su2double *Buffer_Send_Mach = NULL, *Buffer_Recv_Mach = NULL;
10287  Buffer_Send_Mach = new su2double [MaxLocalVertex_Surface];
10288 
10289  su2double *Buffer_Send_Vel_x = NULL, *Buffer_Recv_Vel_x = NULL;
10290  Buffer_Send_Vel_x = new su2double [MaxLocalVertex_Surface];
10291 
10292  su2double *Buffer_Send_Vel_y = NULL, *Buffer_Recv_Vel_y = NULL;
10293  Buffer_Send_Vel_y = new su2double [MaxLocalVertex_Surface];
10294 
10295  su2double *Buffer_Send_Vel_z = NULL, *Buffer_Recv_Vel_z = NULL;
10296  if (nDim == 3) Buffer_Send_Vel_z = new su2double [MaxLocalVertex_Surface];
10297 
10298  su2double *Buffer_Send_q = NULL, *Buffer_Recv_q = NULL;
10299  Buffer_Send_q = new su2double [MaxLocalVertex_Surface];
10300 
10301  su2double *Buffer_Send_Area = NULL, *Buffer_Recv_Area = NULL;
10302  Buffer_Send_Area = new su2double [MaxLocalVertex_Surface];
10303 
10304  /*--- Prepare the receive buffers on the master node only. ---*/
10305 
10306  if (rank == MASTER_NODE) {
10307  Buffer_Recv_Coord_x = new su2double [nProcessor*MaxLocalVertex_Surface];
10308  Buffer_Recv_Coord_y = new su2double [nProcessor*MaxLocalVertex_Surface];
10309  if (nDim == 3) Buffer_Recv_Coord_z = new su2double [nProcessor*MaxLocalVertex_Surface];
10310  Buffer_Recv_PT = new su2double [nProcessor*MaxLocalVertex_Surface];
10311  Buffer_Recv_TT = new su2double [nProcessor*MaxLocalVertex_Surface];
10312  Buffer_Recv_P = new su2double [nProcessor*MaxLocalVertex_Surface];
10313  Buffer_Recv_T = new su2double [nProcessor*MaxLocalVertex_Surface];
10314  Buffer_Recv_Mach = new su2double [nProcessor*MaxLocalVertex_Surface];
10315  Buffer_Recv_Vel_x = new su2double [nProcessor*MaxLocalVertex_Surface];
10316  Buffer_Recv_Vel_y = new su2double [nProcessor*MaxLocalVertex_Surface];
10317  if (nDim == 3) {
10318  Buffer_Recv_Vel_z = new su2double [nProcessor*MaxLocalVertex_Surface];
10319  }
10320  Buffer_Recv_q = new su2double [nProcessor*MaxLocalVertex_Surface];
10321  Buffer_Recv_Area = new su2double [nProcessor*MaxLocalVertex_Surface];
10322  }
10323 
10324  /*--- Loop over all vertices in this partition and load the
10325  data of the specified type into the buffer to be sent to
10326  the master node. ---*/
10327 
10328  nVertex_Surface = 0;
10329  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
10330  string Marker_TagBound = config->GetMarker_All_TagBound(iMarker);
10331  if (Marker_TagBound == Analyze_TagBound) {
10332 
10333  for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
10334  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
10335 
10336  if (geometry->node[iPoint]->GetDomain()) {
10337 
10338  Buffer_Send_Coord_x[nVertex_Surface] = geometry->node[iPoint]->GetCoord(0);
10339  Buffer_Send_Coord_y[nVertex_Surface] = geometry->node[iPoint]->GetCoord(1);
10340  if (nDim == 3) { Buffer_Send_Coord_z[nVertex_Surface] = geometry->node[iPoint]->GetCoord(2); }
10341 
10342  Pressure = solver->node[iPoint]->GetPressure();
10343  Density = solver->node[iPoint]->GetDensity();
10344  Temperature = solver->node[iPoint]->GetTemperature();
10345  SoundSpeed = solver->node[iPoint]->GetSoundSpeed();
10346  Velocity2 = solver->node[iPoint]->GetVelocity2();
10347  Mach = sqrt(Velocity2)/SoundSpeed;
10348  Gamma = config->GetGamma();
10349 
10350  Mach_Inf = config->GetMach();
10351  Pressure_Inf = config->GetPressure_FreeStreamND();
10352  Temperature_Inf = config->GetTemperature_FreeStreamND();
10353  Velocity_Inf = sqrt(config->GetVelocity_FreeStreamND()[0]*config->GetVelocity_FreeStreamND()[0]
10354  + config->GetVelocity_FreeStreamND()[1]*config->GetVelocity_FreeStreamND()[1]
10355  + config->GetVelocity_FreeStreamND()[2]*config->GetVelocity_FreeStreamND()[2]);
10356 
10357  Buffer_Send_P[nVertex_Surface] = Pressure / Pressure_Inf;
10358  Buffer_Send_T[nVertex_Surface] = Temperature / Temperature_Inf;
10359  Buffer_Send_Mach[nVertex_Surface] = Mach;
10360 
10361  TotalPressure = Pressure * pow( 1.0 + Mach * Mach * 0.5 * (Gamma - 1.0), Gamma / (Gamma - 1.0));
10362  TotalPressure_Inf = Pressure_Inf * pow( 1.0 + Mach_Inf * Mach_Inf * 0.5 * (Gamma - 1.0), Gamma / (Gamma - 1.0));
10363  Buffer_Send_PT[nVertex_Surface] = TotalPressure / TotalPressure_Inf;
10364 
10365  TotalTemperature = Temperature * (1.0 + Mach * Mach * 0.5 * (Gamma - 1.0));
10366  TotalTemperature_Inf = Temperature_Inf * (1.0 + Mach * Mach * 0.5 * (Gamma - 1.0));
10367  Buffer_Send_TT[nVertex_Surface] = TotalTemperature / TotalTemperature_Inf;
10368 
10369  Buffer_Send_Vel_x[nVertex_Surface] = solver->node[iPoint]->GetVelocity(0) / Velocity_Inf;
10370  Buffer_Send_Vel_y[nVertex_Surface] = solver->node[iPoint]->GetVelocity(1) / Velocity_Inf;
10371  if (nDim == 3) {
10372  Buffer_Send_Vel_z[nVertex_Surface] = solver->node[iPoint]->GetVelocity(2) / Velocity_Inf;
10373  }
10374 
10375  Buffer_Send_q[nVertex_Surface] = 0.5*Density*Velocity2;
10376 
10377  Vector = geometry->vertex[iMarker][iVertex]->GetNormal();
10378  Area = 0.0; for (iDim = 0; iDim < nDim; iDim++) { Area += Vector[iDim]*Vector[iDim]; } Area = sqrt(Area);
10379  Buffer_Send_Area[nVertex_Surface] = Area;
10380 
10381  /*--- If US system, the output should be in inches ---*/
10382 
10383  if (config->GetSystemMeasurements() == US) {
10384 
10385  Buffer_Send_Coord_x[nVertex_Surface] *= 12.0;
10386  Buffer_Send_Coord_y[nVertex_Surface] *= 12.0;
10387  if (nDim == 3) Buffer_Send_Coord_z[nVertex_Surface] *= 12.0;
10388  Buffer_Send_Area[nVertex_Surface] *= 144.0;
10389 
10390  }
10391 
10392  nVertex_Surface++;
10393 
10394  }
10395  }
10396  break;
10397  }
10398  }
10399 
10400  /*--- Send the information to the master node ---*/
10401 
10402 #ifdef HAVE_MPI
10403 
10404  SU2_MPI::Gather(Buffer_Send_Coord_x, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_x, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10405  SU2_MPI::Gather(Buffer_Send_Coord_y, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_y, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10406  if (nDim == 3) SU2_MPI::Gather(Buffer_Send_Coord_z, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_z, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10407  SU2_MPI::Gather(Buffer_Send_PT, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_PT, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10408  SU2_MPI::Gather(Buffer_Send_TT, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_TT, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10409  SU2_MPI::Gather(Buffer_Send_P, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_P, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10410  SU2_MPI::Gather(Buffer_Send_T, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_T, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10411  SU2_MPI::Gather(Buffer_Send_Mach, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Mach, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10412  SU2_MPI::Gather(Buffer_Send_Vel_x, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Vel_x, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10413  SU2_MPI::Gather(Buffer_Send_Vel_y, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Vel_y, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10414  if (nDim == 3) SU2_MPI::Gather(Buffer_Send_Vel_z, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Vel_z, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10415  SU2_MPI::Gather(Buffer_Send_q, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_q, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10416  SU2_MPI::Gather(Buffer_Send_Area, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Area, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
10417 
10418 #else
10419 
10420  for (iVertex = 0; iVertex < MaxLocalVertex_Surface; iVertex++) {
10421  Buffer_Recv_Coord_x[iVertex] = Buffer_Send_Coord_x[iVertex];
10422  Buffer_Recv_Coord_y[iVertex] = Buffer_Send_Coord_y[iVertex];
10423  if (nDim == 3) Buffer_Recv_Coord_z[iVertex] = Buffer_Send_Coord_z[iVertex];
10424  Buffer_Recv_PT[iVertex] = Buffer_Send_PT[iVertex];
10425  Buffer_Recv_TT[iVertex] = Buffer_Send_TT[iVertex];
10426  Buffer_Recv_P[iVertex] = Buffer_Send_P[iVertex];
10427  Buffer_Recv_T[iVertex] = Buffer_Send_T[iVertex];
10428  Buffer_Recv_Mach[iVertex] = Buffer_Send_Mach[iVertex];
10429  Buffer_Recv_Vel_x[iVertex] = Buffer_Send_Vel_x[iVertex];
10430  Buffer_Recv_Vel_y[iVertex] = Buffer_Send_Vel_y[iVertex];
10431  if (nDim == 3) Buffer_Recv_Vel_z[iVertex] = Buffer_Send_Vel_z[iVertex];
10432  Buffer_Recv_q[iVertex] = Buffer_Send_q[iVertex];
10433  Buffer_Recv_Area[iVertex] = Buffer_Send_Area[iVertex];
10434  }
10435 
10436 #endif
10437 
10438  if (rank == MASTER_NODE) {
10439 
10440  /*--- Compute the location of the critical points of the distortion measure, and center of gravity ---*/
10441 
10442  TotalArea = 0.0; xCoord_CG = 0.0; yCoord_CG = 0.0; zCoord_CG = 0.0; PT_Mean = 0.0; Mach_Mean = 0.0; q_Mean = 0.0;
10443 
10444  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
10445  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) {
10446 
10447  /*--- Current index position and global index ---*/
10448 
10449  Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex;
10450 
10451  /*--- Retrieve the merged data for this node ---*/
10452 
10453  xCoord = Buffer_Recv_Coord_x[Total_Index];
10454  yCoord = Buffer_Recv_Coord_y[Total_Index];
10455  if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index];
10456  PT = Buffer_Recv_PT[Total_Index];
10457  Mach = Buffer_Recv_Mach[Total_Index];
10458  q = Buffer_Recv_q[Total_Index];
10459 
10460  Area = Buffer_Recv_Area[Total_Index];
10461  TotalArea += Area;
10462  xCoord_CG += xCoord*Area;
10463  yCoord_CG += yCoord*Area;
10464  zCoord_CG += zCoord*Area;
10465  PT_Mean += PT*Area;
10466  Mach_Mean += PT*Area;
10467  q_Mean += q*Area;
10468 
10469  }
10470  }
10471 
10472  /*--- Evaluate the area averaged pressure and CG ---*/
10473 
10474  xCoord_CG = xCoord_CG / TotalArea;
10475  yCoord_CG = yCoord_CG / TotalArea;
10476  zCoord_CG = zCoord_CG / TotalArea;
10477  PT_Mean /= TotalArea;
10478  Mach_Mean /= TotalArea;
10479  q_Mean /= TotalArea;
10480 
10481  /*--- If it is a half model, CGy = 0 ---*/
10482 
10483  if (Engine_HalfModel) { yCoord_CG = 0.0; }
10484 
10485  /*--- Compute hub and tip radius ---*/
10486 
10487  TipRadius = 1E-6; HubRadius = 1E6;
10488  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
10489  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) {
10490 
10491  /*--- Current index position and global index ---*/
10492 
10493  Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex;
10494 
10495  /*--- Retrieve the merged data for this node ---*/
10496 
10497  xCoord = Buffer_Recv_Coord_x[Total_Index];
10498  yCoord = Buffer_Recv_Coord_y[Total_Index];
10499  if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index];
10500 
10501  if (nDim == 2)
10502  Distance = sqrt((xCoord_CG-xCoord)*(xCoord_CG-xCoord) +
10503  (yCoord_CG-yCoord)*(yCoord_CG-yCoord));
10504 
10505  if (nDim == 3)
10506  Distance = sqrt((xCoord_CG-xCoord)*(xCoord_CG-xCoord) +
10507  (yCoord_CG-yCoord)*(yCoord_CG-yCoord) +
10508  (zCoord_CG-zCoord)*(zCoord_CG-zCoord));
10509 
10510  if (Distance > TipRadius) TipRadius = Distance;
10511  if (Distance < HubRadius) HubRadius = Distance;
10512 
10513  }
10514  }
10515 
10516  if (HubRadius/TipRadius < 0.05) HubRadius = 0.0;
10517 
10518  /*--- Evaluate the DC60 parameter ---*/
10519 
10520  Theta = Theta_DC60;
10521  nStation = nStation_DC60;
10522 
10523  nAngle = SU2_TYPE::Int(360/float(Theta));
10524  r = new su2double [nStation+1];
10525 
10526  /*--- Allocate memory ---*/
10527 
10528  PT_Sector = new su2double [nAngle];
10529  ProbeArray = new su2double ** [nAngle];
10530  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10531  ProbeArray[iAngle] = new su2double * [nStation];
10532  for (iStation = 0; iStation < nStation; iStation++) {
10533  ProbeArray[iAngle][iStation] = new su2double [5];
10534  }
10535  }
10536 
10537  /*--- Define the radius for each probe ---*/
10538 
10539  r[0] = HubRadius; r[nStation] = TipRadius;
10540  for (iStation = 1; iStation < nStation; iStation++) {
10541  r[iStation] = sqrt( r[iStation-1]*r[iStation-1] + (r[nStation]*r[nStation] - r[0]*r[0])/float(nStation) );
10542  }
10543 
10544  /*--- Define the probe rack ---*/
10545 
10546  UpVector[0] = 0.0; UpVector[1] = 0.0; UpVector[2] = 1.0;
10547 
10548  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10549 
10550  radians = -iAngle*Theta*2.0*PI_NUMBER/360;
10551  RotatedVector[0] = UpVector[0];
10552  RotatedVector[1] = UpVector[1] * cos(radians) - UpVector[2] * sin(radians);
10553  RotatedVector[2] = UpVector[1] * sin(radians) + UpVector[2] * cos(radians);
10554 
10555  for (iStation = 1; iStation <= nStation; iStation++) {
10556  ProbeArray[iAngle][iStation-1][0] = xCoord_CG+RotatedVector[0]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10557  ProbeArray[iAngle][iStation-1][1] = yCoord_CG+RotatedVector[1]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10558  ProbeArray[iAngle][iStation-1][2] = zCoord_CG+RotatedVector[2]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10559  }
10560 
10561  }
10562 
10563  /*--- Compute the Total pressure at each probe, closes grid point to the location ---*/
10564 
10565  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10566 
10567  for (iStation = 0; iStation < nStation; iStation++) {
10568  xCoord_ = ProbeArray[iAngle][iStation][0];
10569  yCoord_ = ProbeArray[iAngle][iStation][1];
10570  zCoord_ = ProbeArray[iAngle][iStation][2];
10571 
10572  MinDistance = 1E6;
10573 
10574  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
10575  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) {
10576 
10577  Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex;
10578  xCoord = Buffer_Recv_Coord_x[Total_Index];
10579  yCoord = Buffer_Recv_Coord_y[Total_Index];
10580  if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index];
10581 
10582  dx = (xCoord_ - xCoord); dy = (yCoord_ - yCoord);
10583  if (nDim == 3) dz = (zCoord_ - zCoord);
10584 
10585  Distance = dx*dx + dy*dy; if (nDim == 3) Distance += dz*dz; Distance = sqrt(Distance);
10586 
10587  if (Engine_HalfModel) {
10588 
10589  yCoord = -yCoord;
10590 
10591  dx_ = (xCoord_ - xCoord); dy_ = (yCoord_ - yCoord);
10592  if (nDim == 3) dz_ = (zCoord_ - zCoord);
10593 
10594  Distance_Mirror = dx_*dx_ + dy_*dy_;
10595  if (nDim == 3) Distance_Mirror += dz_*dz_;
10596  Distance_Mirror = sqrt(Distance_Mirror);
10597 
10598  if (Distance_Mirror < Distance) {
10599  Distance = Distance_Mirror;
10600  dx = dx_; dy = dy_;
10601  if (nDim == 3) dz = dz_;
10602  }
10603 
10604  }
10605 
10606  if (Distance <= MinDistance) {
10607  MinDistance = Distance;
10608  ProbeArray[iAngle][iStation][3] = Buffer_Recv_PT[Total_Index];
10609  ProbeArray[iAngle][iStation][4] = Buffer_Recv_q[Total_Index];
10610  }
10611 
10612  }
10613  }
10614 
10615  }
10616 
10617  }
10618 
10619  /*--- Evaluate the average pressure at each sector, fan face and dynamic pressure ---*/
10620 
10621  PT_Mean = 0.0; q_Mean = 0.0;
10622  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10623  PT_Sector[iAngle] = 0.0;
10624  for (iStation = 0; iStation < nStation; iStation++) {
10625  PT_Sector[iAngle] += ProbeArray[iAngle][iStation][3]/float(nStation);
10626  PT_Mean += ProbeArray[iAngle][iStation][3]/float(nStation*nAngle);
10627  q_Mean += ProbeArray[iAngle][iStation][4]/float(nStation*nAngle);
10628  }
10629  }
10630 
10631  /*--- Compute the min value of the averaged pressure at each sector ---*/
10632 
10633  PT_Sector_Min = PT_Sector[0];
10634  for (iAngle = 1; iAngle < nAngle; iAngle++) {
10635  if (PT_Sector[iAngle] <= PT_Sector_Min) PT_Sector_Min = PT_Sector[iAngle];
10636  }
10637 
10638  /*--- Set the value of the distortion, it only works for one surface ---*/
10639 
10640  Mach_Inf = config->GetMach();
10641  Gamma = config->GetGamma();
10642  TotalPressure_Inf = config->GetPressure_FreeStreamND() * pow( 1.0 + Mach_Inf * Mach_Inf *
10643  0.5 * (Gamma - 1.0), Gamma / (Gamma - 1.0));
10644 
10645  if (q_Mean != 0.0) DC60 = ((PT_Mean - PT_Sector_Min)*TotalPressure_Inf)/q_Mean;
10646  else DC60 = 0.0;
10647 
10648  config->SetSurface_DC60(iMarker_Analyze, DC60);
10649 
10650  solver->SetTotal_DC60(DC60);
10651 
10652  /*--- Deallocate the memory ---*/
10653 
10654  delete[] r;
10655 
10656  delete [] PT_Sector;
10657 
10658  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10659  for (iStation = 0; iStation < nStation; iStation++) {
10660  delete[] ProbeArray[iAngle][iStation];
10661  }
10662  }
10663  delete[] ProbeArray;
10664 
10665 
10666  /*--- Evaluate the IDC, and IDR parameters ---*/
10667 
10668  nStation = SU2_TYPE::Int(config->GetDistortionRack()[0]);
10669  Theta = SU2_TYPE::Int(config->GetDistortionRack()[1]);
10670  nAngle = SU2_TYPE::Int(360/float(Theta));
10671 
10672  /*--- Allocate memory ---*/
10673 
10674  r = new su2double [nStation+1];
10675  ProbeArray = new su2double ** [nAngle];
10676  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10677  ProbeArray[iAngle] = new su2double * [nStation];
10678  for (iStation = 0; iStation < nStation; iStation++) {
10679  ProbeArray[iAngle][iStation] = new su2double [4];
10680  }
10681  }
10682 
10683  /*--- Define the radius for each probe ---*/
10684 
10685  r[0] = HubRadius; r[nStation] = TipRadius;
10686  for (iStation = 1; iStation < nStation; iStation++) {
10687  r[iStation] = sqrt( r[iStation-1]*r[iStation-1] + (r[nStation]*r[nStation] - r[0]*r[0])/float(nStation) );
10688  }
10689 
10690  /*--- Define the probe rack ---*/
10691 
10692  UpVector[0] = 0.0; UpVector[1] = 0.0; UpVector[2] = 1.0;
10693 
10694  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10695 
10696  radians = -iAngle*Theta*2.0*PI_NUMBER/360;
10697  RotatedVector[0] = UpVector[0];
10698  RotatedVector[1] = UpVector[1] * cos(radians) - UpVector[2] * sin(radians);
10699  RotatedVector[2] = UpVector[1] * sin(radians) + UpVector[2] * cos(radians);
10700 
10701  for (iStation = 1; iStation <= nStation; iStation++) {
10702  ProbeArray[iAngle][iStation-1][0] = xCoord_CG+RotatedVector[0]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10703  ProbeArray[iAngle][iStation-1][1] = yCoord_CG+RotatedVector[1]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10704  ProbeArray[iAngle][iStation-1][2] = zCoord_CG+RotatedVector[2]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10705  }
10706 
10707  }
10708 
10709  /*--- Compute the Total pressure at each probe, closes grid point to the location ---*/
10710 
10711  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10712  for (iStation = 0; iStation < nStation; iStation++) {
10713  xCoord_ = ProbeArray[iAngle][iStation][0];
10714  yCoord_ = ProbeArray[iAngle][iStation][1];
10715  zCoord_ = ProbeArray[iAngle][iStation][2];
10716 
10717  MinDistance = 1E6;
10718 
10719  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
10720  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) {
10721 
10722  Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex;
10723  xCoord = Buffer_Recv_Coord_x[Total_Index];
10724  yCoord = Buffer_Recv_Coord_y[Total_Index];
10725  if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index];
10726 
10727  dx = (xCoord_ - xCoord); dy = (yCoord_ - yCoord);
10728  if (nDim == 3) dz = (zCoord_ - zCoord);
10729 
10730  Distance = dx*dx + dy*dy; if (nDim == 3) Distance += dz*dz; Distance = sqrt(Distance);
10731 
10732  if (Engine_HalfModel) {
10733 
10734  yCoord = -yCoord;
10735 
10736  dx_ = (xCoord_ - xCoord); dy_ = (yCoord_ - yCoord);
10737  if (nDim == 3) dz_ = (zCoord_ - zCoord);
10738 
10739  Distance_Mirror = dx_*dx_ + dy_*dy_;
10740  if (nDim == 3) Distance_Mirror += dz_*dz_;
10741  Distance_Mirror = sqrt(Distance_Mirror);
10742 
10743  if (Distance_Mirror < Distance) {
10744  Distance = Distance_Mirror;
10745  dx = dx_; dy = dy_;
10746  if (nDim == 3) dz = dz_;
10747  }
10748 
10749  }
10750 
10751  if (Distance <= MinDistance) {
10752  MinDistance = Distance;
10753  ProbeArray[iAngle][iStation][3] = Buffer_Recv_PT[Total_Index];
10754  }
10755 
10756  }
10757  }
10758 
10759  }
10760 
10761  }
10762 
10763  /*--- Evaluate the average and min. pressure at each station/radius and fan ---*/
10764 
10765  PT_Station = new su2double [nStation];
10766  PT_Station_Min = new su2double [nStation];
10767 
10768  PT_Mean = 0.0;
10769  for (iStation = 0; iStation < nStation; iStation++) {
10770  PT_Station[iStation] = 0.0;
10771  PT_Station_Min[iStation] = ProbeArray[0][iStation][3];
10772  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10773  PT = ProbeArray[iAngle][iStation][3];
10774  PT_Station[iStation] += PT / float(nAngle);
10775  if (PT <= PT_Station_Min[iStation] ) PT_Station_Min[iStation] = PT;
10776  PT_Mean += ProbeArray[iAngle][iStation][3]/float(nStation*nAngle);
10777  }
10778  }
10779 
10780  /*--- Set the value of the distortion, it only works for one surface ---*/
10781 
10782  IDC = 0.0;
10783  for (iStation = 0; iStation < nStation-1; iStation++) {
10784  IDC = max (IDC, 0.5*((PT_Station[iStation] - PT_Station_Min[iStation])/PT_Mean
10785  + (PT_Station[iStation+1] - PT_Station_Min[iStation+1])/PT_Mean) );
10786 
10787  }
10788 
10789  config->SetSurface_IDC(iMarker_Analyze, IDC);
10790  solver->SetTotal_IDC(IDC);
10791 
10792  IDR = 0.0;
10793  for (iStation = 0; iStation < nStation; iStation++) {
10794  IDR = max (IDR, (PT_Mean-PT_Station[iStation])/PT_Mean);
10795  }
10796 
10797  config->SetSurface_IDR(iMarker_Analyze, IDR);
10798 
10799  solver->SetTotal_IDR(IDR);
10800 
10801  /*--- Release IDX parameters ---*/
10802 
10803  delete [] PT_Station_Min;
10804  delete [] PT_Station;
10805 
10806  /*--- Evaluate the IDC Mach parameter ---*/
10807 
10808  /*--- Compute the Mach number at each probe, closes grid point to the location ---*/
10809 
10810  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10811  for (iStation = 0; iStation < nStation; iStation++) {
10812  xCoord_ = ProbeArray[iAngle][iStation][0];
10813  yCoord_ = ProbeArray[iAngle][iStation][1];
10814  zCoord_ = ProbeArray[iAngle][iStation][2];
10815 
10816  MinDistance = 1E6;
10817 
10818  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
10819  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) {
10820 
10821  Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex;
10822 
10823  xCoord = Buffer_Recv_Coord_x[Total_Index];
10824  yCoord = Buffer_Recv_Coord_y[Total_Index];
10825  if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index];
10826 
10827  dx = (xCoord_ - xCoord); dy = (yCoord_ - yCoord);
10828  if (nDim == 3) dz = (zCoord_ - zCoord);
10829 
10830  Distance = dx*dx + dy*dy;
10831  if (nDim == 3) Distance += dz*dz;
10832  Distance = sqrt(Distance);
10833 
10834  if (Engine_HalfModel) {
10835 
10836  yCoord = -yCoord;
10837 
10838  dx_ = (xCoord_ - xCoord); dy_ = (yCoord_ - yCoord);
10839  if (nDim == 3) dz_ = (zCoord_ - zCoord);
10840 
10841  Distance_Mirror = dx_*dx_ + dy_*dy_;
10842  if (nDim == 3) Distance_Mirror += dz_*dz_;
10843  Distance_Mirror = sqrt(Distance_Mirror);
10844 
10845  if (Distance_Mirror < Distance) {
10846  Distance = Distance_Mirror;
10847  dx = dx_; dy = dy_;
10848  if (nDim == 3) dz = dz_;
10849  }
10850 
10851  }
10852 
10853  if (Distance <= MinDistance) {
10854  MinDistance = Distance;
10855  ProbeArray[iAngle][iStation][3] = Buffer_Recv_Mach[Total_Index];
10856  }
10857 
10858  }
10859  }
10860 
10861  }
10862 
10863  }
10864 
10865  /*--- Evaluate the average and min. pressure at each station/radius and fan face ---*/
10866 
10867  Mach_Station = new su2double [nStation];
10868  Mach_Station_Min = new su2double [nStation];
10869 
10870  Mach_Mean = 0.0;
10871  for (iStation = 0; iStation < nStation; iStation++) {
10872  Mach_Station[iStation] = 0.0;
10873  Mach_Station_Min[iStation] = ProbeArray[0][iStation][3];
10874  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10875  Mach = ProbeArray[iAngle][iStation][3];
10876  Mach_Station[iStation] += Mach / float(nAngle);
10877  if (Mach <= Mach_Station_Min[iStation] ) Mach_Station_Min[iStation] = Mach;
10878  Mach_Mean += ProbeArray[iAngle][iStation][3]/float(nStation*nAngle);
10879  }
10880  }
10881 
10882  /*--- Set the value of the distortion, it only works for one surface ---*/
10883 
10884  IDC_Mach = 0.0;
10885  for (iStation = 0; iStation < nStation-1; iStation++) {
10886  if (Mach_Mean != 0)
10887  IDC_Mach = max (IDC_Mach, 0.5*((Mach_Station[iStation] - Mach_Station_Min[iStation])/Mach_Mean
10888  + (Mach_Station[iStation+1] - Mach_Station_Min[iStation+1])/Mach_Mean) );
10889 
10890  }
10891 
10892  config->SetSurface_IDC_Mach(iMarker_Analyze, IDC_Mach);
10893 
10894  solver->SetTotal_IDC_Mach(IDC_Mach);
10895 
10896  delete [] Mach_Station_Min;
10897  delete [] Mach_Station;
10898 
10899  /*--- Release distortion parameters ---*/
10900 
10901  delete[] r;
10902  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10903  for (iStation = 0; iStation < nStation; iStation++) {
10904  delete[] ProbeArray[iAngle][iStation];
10905  }
10906  }
10907  delete[] ProbeArray;
10908 
10909  /*--- Create the distortion plot ---*/
10910 
10911  Theta = 10; nStation = 20;
10912 
10913  nAngle = SU2_TYPE::Int(360/float(Theta));
10914  r = new su2double [nStation+1];
10915 
10916  /*--- Allocate memory ---*/
10917 
10918  ProbeArray = new su2double ** [nAngle];
10919  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10920  ProbeArray[iAngle] = new su2double * [nStation];
10921  for (iStation = 0; iStation < nStation; iStation++) {
10922  ProbeArray[iAngle][iStation] = new su2double [11];
10923  }
10924  }
10925 
10926  /*--- Define the radius for each probe ---*/
10927 
10928  r[0] = HubRadius;
10929  r[nStation] = TipRadius;
10930 
10931  for (iStation = 1; iStation < nStation; iStation++) {
10932  r[iStation] = sqrt( r[iStation-1]*r[iStation-1] + (r[nStation]*r[nStation] - r[0]*r[0])/float(nStation) );
10933  }
10934 
10935  /*--- Define the probe rack ---*/
10936 
10937  UpVector[0] = 0.0; UpVector[1] = 0.0; UpVector[2] = 1.0;
10938 
10939  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10940 
10941  radians = -iAngle*Theta*2.0*PI_NUMBER/360;
10942  RotatedVector[0] = UpVector[0];
10943  RotatedVector[1] = UpVector[1] * cos(radians) - UpVector[2] * sin(radians);
10944  RotatedVector[2] = UpVector[1] * sin(radians) + UpVector[2] * cos(radians);
10945 
10946  for (iStation = 1; iStation <= nStation; iStation++) {
10947  ProbeArray[iAngle][iStation-1][0] = xCoord_CG+RotatedVector[0]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10948  ProbeArray[iAngle][iStation-1][1] = yCoord_CG+RotatedVector[1]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10949  ProbeArray[iAngle][iStation-1][2] = zCoord_CG+RotatedVector[2]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1]));
10950  }
10951 
10952  }
10953 
10954  /*--- Compute the primitieve variables, closest grid point to the location + gradient ---*/
10955 
10956  for (iAngle = 0; iAngle < nAngle; iAngle++) {
10957  for (iStation = 0; iStation < nStation; iStation++) {
10958  xCoord_ = ProbeArray[iAngle][iStation][0];
10959  yCoord_ = ProbeArray[iAngle][iStation][1];
10960  zCoord_ = ProbeArray[iAngle][iStation][2];
10961 
10962  MinDistance = 1E6;
10963 
10964  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
10965  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) {
10966 
10967  Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex;
10968  xCoord = Buffer_Recv_Coord_x[Total_Index];
10969  yCoord = Buffer_Recv_Coord_y[Total_Index];
10970  if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index];
10971 
10972  dx = (xCoord_ - xCoord); dy = (yCoord_ - yCoord);
10973  if (nDim == 3) dz = (zCoord_ - zCoord);
10974 
10975  Distance = dx*dx + dy*dy; if (nDim == 3) Distance += dz*dz; Distance = sqrt(Distance);
10976 
10977  SignFlip = 1.0;
10978 
10979  if (Engine_HalfModel) {
10980 
10981  yCoord = -yCoord;
10982 
10983  dx_ = (xCoord_ - xCoord);
10984  dy_ = (yCoord_ - yCoord);
10985  if (nDim == 3) dz_ = (zCoord_ - zCoord);
10986 
10987  Distance_Mirror = dx_*dx_ + dy_*dy_;
10988  if (nDim == 3) Distance_Mirror += dz_*dz_;
10989  Distance_Mirror = sqrt(Distance_Mirror);
10990 
10991  if (Distance_Mirror < Distance) {
10992  SignFlip = -1.0;
10993  Distance = Distance_Mirror;
10994  dx = dx_; dy = dy_;
10995  if (nDim == 3) dz = dz_;
10996  }
10997 
10998  }
10999 
11000 
11001  if (Distance <= MinDistance) {
11002  MinDistance = Distance;
11003  ProbeArray[iAngle][iStation][3] = Buffer_Recv_PT[Total_Index];
11004  ProbeArray[iAngle][iStation][4] = Buffer_Recv_TT[Total_Index];
11005  ProbeArray[iAngle][iStation][5] = Buffer_Recv_P[Total_Index];
11006  ProbeArray[iAngle][iStation][6] = Buffer_Recv_T[Total_Index];
11007  ProbeArray[iAngle][iStation][7] = Buffer_Recv_Mach[Total_Index];
11008  ProbeArray[iAngle][iStation][8] = Buffer_Recv_Vel_x[Total_Index];
11009  ProbeArray[iAngle][iStation][9] = SignFlip * Buffer_Recv_Vel_y[Total_Index];
11010  if (nDim == 3) ProbeArray[iAngle][iStation][10] = Buffer_Recv_Vel_z[Total_Index];
11011  }
11012 
11013  }
11014  }
11015 
11016  }
11017 
11018  }
11019 
11020  /*--- Reverse in the Y direction to move the solution from 3D to 2D ---*/
11021 
11022  yCoord_CG = -yCoord_CG;
11023  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11024  for (iStation = 0; iStation < nStation; iStation++) {
11025  ProbeArray[iAngle][iStation][9] = -ProbeArray[iAngle][iStation][9];
11026  ProbeArray[iAngle][iStation][1] = -ProbeArray[iAngle][iStation][1];
11027  }
11028  }
11029 
11030  if (output) {
11031 
11032  if ((config->GetOutput_FileFormat() == PARAVIEW) || (config->GetOutput_FileFormat() == PARAVIEW_BINARY)) {
11033 
11034  SurfFlow_file << "\nDATASET UNSTRUCTURED_GRID" << endl;
11035  SurfFlow_file <<"POINTS " << nAngle*nStation << " float" << endl;
11036  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11037  for (iStation = 0; iStation < nStation; iStation++) {
11038  SurfFlow_file << ProbeArray[iAngle][iStation][1]-yCoord_CG << " " << ProbeArray[iAngle][iStation][2]-zCoord_CG << " 0.0 " <<" ";
11039  }
11040  }
11041 
11042  SurfFlow_file <<"\nCELLS " << nAngle*(nStation-1) <<" "<< nAngle*(nStation-1)*5 << endl;
11043  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11044  for (iStation = 0; iStation < nStation-1; iStation++) {
11045  a = iAngle*nStation+iStation; b = a + nStation; c = b+1; d = a +1;
11046  if (iAngle == nAngle-1) { b = iStation; c = b+1; }
11047  SurfFlow_file << "4 " << a <<" "<< b <<" "<< c <<" "<< d <<" ";
11048  }
11049  }
11050 
11051  SurfFlow_file <<"\nCELL_TYPES " << nAngle*(nStation-1) << endl;
11052  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11053  for (iStation = 0; iStation < nStation-1; iStation++) {
11054  SurfFlow_file << "9 " ;
11055  }
11056  }
11057 
11058  SurfFlow_file <<"\nPOINT_DATA " << nAngle*nStation << endl;
11059  SurfFlow_file <<"SCALARS PT/PT_inf float" << endl;
11060  SurfFlow_file <<"LOOKUP_TABLE default" << endl;
11061 
11062  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11063  for (iStation = 0; iStation < nStation; iStation++) {
11064  SurfFlow_file << ProbeArray[iAngle][iStation][3] << " ";
11065  }
11066  }
11067 
11068  SurfFlow_file <<"SCALARS TT/TT_inf float" << endl;
11069  SurfFlow_file <<"LOOKUP_TABLE default" << endl;
11070 
11071  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11072  for (iStation = 0; iStation < nStation; iStation++) {
11073  SurfFlow_file << ProbeArray[iAngle][iStation][4] << " ";
11074  }
11075  }
11076 
11077  SurfFlow_file <<"SCALARS Alpha float" << endl;
11078  SurfFlow_file <<"LOOKUP_TABLE default" << endl;
11079 
11080  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11081  for (iStation = 0; iStation < nStation; iStation++) {
11082  Alpha = atan(ProbeArray[iAngle][iStation][10]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER);
11083  SurfFlow_file << Alpha << " ";
11084  }
11085  }
11086 
11087  SurfFlow_file <<"SCALARS Beta float" << endl;
11088  SurfFlow_file <<"LOOKUP_TABLE default" << endl;
11089 
11090  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11091  for (iStation = 0; iStation < nStation; iStation++) {
11092  Beta = atan(ProbeArray[iAngle][iStation][9]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER);
11093  SurfFlow_file << Beta << " ";
11094  }
11095  }
11096 
11097  SurfFlow_file <<"SCALARS Mach float" << endl;
11098  SurfFlow_file <<"LOOKUP_TABLE default" << endl;
11099 
11100  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11101  for (iStation = 0; iStation < nStation; iStation++) {
11102  SurfFlow_file << ProbeArray[iAngle][iStation][7] << " ";
11103  }
11104  }
11105 
11106  SurfFlow_file <<"VECTORS Velocity float" << endl;
11107 
11108  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11109  for (iStation = 0; iStation < nStation; iStation++) {
11110  SurfFlow_file << ProbeArray[iAngle][iStation][8] << " " << ProbeArray[iAngle][iStation][9] << " " << ProbeArray[iAngle][iStation][10] << " ";
11111  }
11112  }
11113 
11114  }
11115  else {
11116 
11117  SurfFlow_file <<"ZONE T= \"" << Analyze_TagBound <<"\", NODES=" << nAngle*nStation << " , ELEMENTS= " << nAngle*(nStation-1) <<", DATAPACKING=POINT, ZONETYPE=FEQUADRILATERAL" << endl;
11118 
11119  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11120  for (iStation = 0; iStation < nStation; iStation++) {
11121 
11122  Alpha = atan(ProbeArray[iAngle][iStation][10]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER);
11123  Beta = atan(ProbeArray[iAngle][iStation][9]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER);
11124 
11125  Mach_ij = ProbeArray[iAngle][iStation][7];
11126  if (iAngle+1 != nAngle) Mach_ip1j = ProbeArray[iAngle+1][iStation][7];
11127  else Mach_ip1j = ProbeArray[0][iStation][7];
11128  if (iAngle-1 != -1) Mach_im1j = ProbeArray[iAngle-1][iStation][7];
11129  else Mach_im1j = ProbeArray[nAngle-1][iStation][7];
11130  if (iStation+1 != nStation) Mach_ijp1 = ProbeArray[iAngle][iStation+1][7];
11131  else Mach_ijp1 = ProbeArray[iAngle][0][7];
11132  if (iStation-1 != -1) Mach_ijm1 = ProbeArray[iAngle][iStation-1][7];
11133  else Mach_ijm1 = ProbeArray[iAngle][nStation-1][7];
11134  Filtered_Mach = (4.0*Mach_ij+Mach_ip1j+Mach_im1j+Mach_ijp1+Mach_ijm1)/8.0;
11135 
11136  Alpha_ij = atan(ProbeArray[iAngle][iStation][10]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER);
11137  if (iAngle+1 != nAngle) Alpha_ip1j = atan(ProbeArray[iAngle+1][iStation][10]/ProbeArray[iAngle+1][iStation][8])*360.0/(2.0*PI_NUMBER);
11138  else Alpha_ip1j = atan(ProbeArray[0][iStation][10]/ProbeArray[0][iStation][8])*360.0/(2.0*PI_NUMBER);
11139  if (iAngle-1 != -1) Alpha_im1j = atan(ProbeArray[iAngle-1][iStation][10]/ProbeArray[iAngle-1][iStation][8])*360.0/(2.0*PI_NUMBER);
11140  else Alpha_im1j = atan(ProbeArray[nAngle-1][iStation][10]/ProbeArray[nAngle-1][iStation][8])*360.0/(2.0*PI_NUMBER);
11141  if (iStation+1 != nStation) Alpha_ijp1 = atan(ProbeArray[iAngle][iStation+1][10]/ProbeArray[iAngle][iStation+1][8])*360.0/(2.0*PI_NUMBER);
11142  else Alpha_ijp1 = atan(ProbeArray[iAngle][0][10]/ProbeArray[iAngle][0][8])*360.0/(2.0*PI_NUMBER);
11143  if (iStation-1 != -1) Alpha_ijm1 = atan(ProbeArray[iAngle][iStation-1][10]/ProbeArray[iAngle][iStation-1][8])*360.0/(2.0*PI_NUMBER);
11144  else Alpha_ijm1 = atan(ProbeArray[iAngle][nStation-1][10]/ProbeArray[iAngle][nStation-1][8])*360.0/(2.0*PI_NUMBER);
11145  Filtered_Alpha = (4.0*Alpha_ij+Alpha_ip1j+Alpha_im1j+Alpha_ijp1+Alpha_ijm1)/8.0;
11146 
11147  Beta_ij = atan(ProbeArray[iAngle][iStation][9]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER);
11148  if (iAngle+1 != nAngle) Beta_ip1j = atan(ProbeArray[iAngle+1][iStation][9]/ProbeArray[iAngle+1][iStation][8])*360.0/(2.0*PI_NUMBER);
11149  else Beta_ip1j = atan(ProbeArray[0][iStation][9]/ProbeArray[0][iStation][8])*360.0/(2.0*PI_NUMBER);
11150  if (iAngle-1 != -1) Beta_im1j = atan(ProbeArray[iAngle-1][iStation][9]/ProbeArray[iAngle-1][iStation][8])*360.0/(2.0*PI_NUMBER);
11151  else Beta_im1j = atan(ProbeArray[nAngle-1][iStation][9]/ProbeArray[nAngle-1][iStation][8])*360.0/(2.0*PI_NUMBER);
11152  if (iStation+1 != nStation) Beta_ijp1 = atan(ProbeArray[iAngle][iStation+1][9]/ProbeArray[iAngle][iStation+1][8])*360.0/(2.0*PI_NUMBER);
11153  else Beta_ijp1 = atan(ProbeArray[iAngle][0][9]/ProbeArray[iAngle][0][8])*360.0/(2.0*PI_NUMBER);
11154  if (iStation-1 != -1) Beta_ijm1 = atan(ProbeArray[iAngle][iStation-1][9]/ProbeArray[iAngle][iStation-1][8])*360.0/(2.0*PI_NUMBER);
11155  else Beta_ijm1 = atan(ProbeArray[iAngle][nStation-1][9]/ProbeArray[iAngle][nStation-1][8])*360.0/(2.0*PI_NUMBER);
11156  Filtered_Beta = (4.0*Beta_ij+Beta_ip1j+Beta_im1j+Beta_ijp1+Beta_ijm1)/8.0;
11157 
11158 
11159  SurfFlow_file
11160  << " " << ProbeArray[iAngle][iStation][1]-yCoord_CG
11161  <<" " << ProbeArray[iAngle][iStation][2]-zCoord_CG
11162  <<" " << ProbeArray[iAngle][iStation][3] <<" " << ProbeArray[iAngle][iStation][4]
11163  <<" " << ProbeArray[iAngle][iStation][5] <<" " << ProbeArray[iAngle][iStation][6]
11164  <<" " << ProbeArray[iAngle][iStation][8] <<" " << ProbeArray[iAngle][iStation][9]
11165  <<" " << ProbeArray[iAngle][iStation][10]
11166  <<" " << Alpha <<" " << Beta << " " << ProbeArray[iAngle][iStation][7]
11167  <<" " << Filtered_Alpha <<" " << Filtered_Beta << " " << Filtered_Mach << endl;
11168 
11169  }
11170  }
11171 
11172  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11173  for (iStation = 0; iStation < nStation-1; iStation++) {
11174  a = iAngle*nStation+iStation; b = a + nStation; c = b+1; d = a +1;
11175  if (iAngle == nAngle-1) { b = iStation; c = b+1; }
11176  SurfFlow_file << a+1 <<" "<< b+1 <<" "<< c+1 <<" "<< d+1 << endl;
11177  }
11178  }
11179 
11180  /*--- Add extra info ---*/
11181 
11182  SurfFlow_file << "TEXT X=14, Y=86, F=HELV-BOLD, C=BLUE, H=2.0, ";
11183  unsigned short RackProbes = SU2_TYPE::Int(config->GetDistortionRack()[0]);
11184  unsigned short RackAngle = SU2_TYPE::Int(config->GetDistortionRack()[1]);
11185  SurfFlow_file << "T=\"Rack Size: " << RackProbes << " probes at "<< RackAngle << "deg." << "\\" << "\\n";
11186  SurfFlow_file << "Mach " << config->GetMach() << ", Reynolds " << config->GetReynolds() << ", <greek>a</greek> "
11187  << config->GetAoA() << "deg, <greek>b</greek> " << config->GetAoS() << "deg." << "\\" << "\\n";
11188  SurfFlow_file.precision(1);
11189  SurfFlow_file << fixed << "Net Thrust " << solver->GetTotal_NetThrust() << "lbs, Power " << solver->GetTotal_Power() << "HP";
11190  SurfFlow_file.precision(4);
11191  SurfFlow_file << ", MassFlow " << config->GetSurface_MassFlow(iMarker_Analyze) << ",\\" << "\\n";
11192  SurfFlow_file << "IDC " << config->GetSurface_IDC(iMarker_Analyze)*100 << "%, IDCM " << config->GetSurface_IDC_Mach(iMarker_Analyze)*100 << "%, IDR " << config->GetSurface_IDR(iMarker_Analyze)*100 << "%,\\" << "\\n";
11193  SurfFlow_file << "DC60 " << config->GetSurface_DC60(iMarker_Analyze) << ".\"" << endl;
11194 
11195  }
11196 
11197  }
11198 
11199  /*--- Release the recv buffers on the master node ---*/
11200 
11201  delete [] Buffer_Recv_Coord_x;
11202  delete [] Buffer_Recv_Coord_y;
11203  if (nDim == 3) delete [] Buffer_Recv_Coord_z;
11204 
11205  delete [] Buffer_Recv_PT;
11206  delete [] Buffer_Recv_TT;
11207  delete [] Buffer_Recv_P;
11208  delete [] Buffer_Recv_T;
11209  delete [] Buffer_Recv_Mach;
11210  delete [] Buffer_Recv_Vel_x;
11211  delete [] Buffer_Recv_Vel_y;
11212  if (nDim == 3) delete [] Buffer_Recv_Vel_z;
11213  delete [] Buffer_Recv_q;
11214 
11215  delete [] Buffer_Recv_Area;
11216 
11217  delete [] Buffer_Recv_nVertex;
11218 
11219  delete[] r;
11220  for (iAngle = 0; iAngle < nAngle; iAngle++) {
11221  for (iStation = 0; iStation < nStation; iStation++) {
11222  delete[] ProbeArray[iAngle][iStation];
11223  }
11224  }
11225  delete[] ProbeArray;
11226 
11227  }
11228 
11229 // if ((rank == MASTER_NODE) && !config->GetDiscrete_Adjoint()) {
11230 //
11231 // cout << "Surface ("<< Analyze_TagBound << "): ";
11232 // cout.precision(4);
11233 // cout.setf(ios::fixed, ios::floatfield);
11234 // cout << setprecision(1) << "IDC " << 100*config->GetSurface_IDC(iMarker_Analyze)
11235 // << "%. IDC Mach " << 100*config->GetSurface_IDC_Mach(iMarker_Analyze)
11236 // << "%. IDR " << 100*config->GetSurface_IDR(iMarker_Analyze)
11237 // << "%. DC60 " << config->GetSurface_DC60(iMarker_Analyze) << "." << endl;
11238 //
11239 // }
11240 
11241  /*--- Release the memory for the remaining buffers and exit ---*/
11242 
11243  delete [] Buffer_Send_Coord_x;
11244  delete [] Buffer_Send_Coord_y;
11245  if (nDim == 3) delete [] Buffer_Send_Coord_z;
11246 
11247  delete [] Buffer_Send_PT;
11248  delete [] Buffer_Send_TT;
11249  delete [] Buffer_Send_P;
11250  delete [] Buffer_Send_T;
11251  delete [] Buffer_Send_Mach;
11252  delete [] Buffer_Send_Vel_x;
11253  delete [] Buffer_Send_Vel_y;
11254  if (nDim == 3) delete [] Buffer_Send_Vel_z;
11255  delete [] Buffer_Send_q;
11256 
11257  delete [] Buffer_Send_Area;
11258 
11259  }
11260 
11261  /*--- Close the tecplot file ---*/
11262 
11263  if (output) {
11264  SurfFlow_file.close();
11265  }
11266 
11267 }
11268 
11269 void COutput::SpecialOutput_FSI(ofstream *FSIHist_file, CGeometry ****geometry, CSolver *****solver_container,
11270  CConfig **config, CIntegration ****integration, unsigned long iExtIter,
11271  unsigned short ZONE_FLOW, unsigned short ZONE_STRUCT, bool header) {
11272 
11273  int rank = MASTER_NODE;
11274 #ifdef HAVE_MPI
11275  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
11276 #endif
11277 
11278  /*--- Output only using the Master Node ---*/
11279 
11280  if ((rank == MASTER_NODE) && (header)){
11281 
11282  char cstr[200], buffer[50], turb_resid[1000];
11283  string Monitoring_Tag, monitoring_coeff, aeroelastic_coeff, turbo_coeff;
11284 
11285  bool turbulent = ((config[ZONE_FLOW]->GetKind_Solver() == RANS) || (config[ZONE_FLOW]->GetKind_Solver() == ADJ_RANS) ||
11286  (config[ZONE_FLOW]->GetKind_Solver() == DISC_ADJ_RANS));
11287 
11288  unsigned short direct_diff = config[ZONE_FLOW]->GetDirectDiff();
11289 
11290  /*--- Write file name with extension ---*/
11291  string filename = config[ZONE_FLOW]->GetConv_FileName_FSI();
11292  strcpy (cstr, filename.data());
11293 
11294  if (config[ZONE_FLOW]->GetWrt_Unsteady() && config[ZONE_FLOW]->GetRestart()) {
11295  long iExtIter = config[ZONE_FLOW]->GetUnst_RestartIter();
11296  if (SU2_TYPE::Int(iExtIter) < 10) SPRINTF (buffer, "_0000%d", SU2_TYPE::Int(iExtIter));
11297  if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d", SU2_TYPE::Int(iExtIter));
11298  if ((SU2_TYPE::Int(iExtIter) >= 100) && (SU2_TYPE::Int(iExtIter) < 1000)) SPRINTF (buffer, "_00%d", SU2_TYPE::Int(iExtIter));
11299  if ((SU2_TYPE::Int(iExtIter) >= 1000) && (SU2_TYPE::Int(iExtIter) < 10000)) SPRINTF (buffer, "_0%d", SU2_TYPE::Int(iExtIter));
11300  if (SU2_TYPE::Int(iExtIter) >= 10000) SPRINTF (buffer, "_%d", SU2_TYPE::Int(iExtIter));
11301  strcat(cstr, buffer);
11302  }
11303 
11304  if ((config[ZONE_FLOW]->GetOutput_FileFormat() == TECPLOT) ||
11305  (config[ZONE_FLOW]->GetOutput_FileFormat() == FIELDVIEW)) SPRINTF (buffer, ".dat");
11306  else if ((config[ZONE_FLOW]->GetOutput_FileFormat() == TECPLOT_BINARY) ||
11307  (config[ZONE_FLOW]->GetOutput_FileFormat() == FIELDVIEW_BINARY)) SPRINTF (buffer, ".plt");
11308  else if ((config[ZONE_FLOW]->GetOutput_FileFormat() == PARAVIEW) || (config[ZONE_FLOW]->GetOutput_FileFormat() == PARAVIEW_BINARY)) SPRINTF (buffer, ".vtk");
11309  strcat(cstr, buffer);
11310 
11311  FSIHist_file->open(cstr, ios::out);
11312  FSIHist_file->precision(15);
11313 
11314  /*--- Begin of the header ---*/
11315 
11316  char begin[]= "\"ExtIter\",\"BGSIter\"";
11317 
11318  /*--- Header for the coefficients ---*/
11319 
11320  char flow_coeff[]= ",\"CL\",\"CD\",\"CMx\",\"CMy\",\"CMz\",\"CL/CD\"";
11321  char fem_coeff[]= ",\"VM_Stress\"";
11322  char of_1[] = ",\"TgtGeom\"";
11323  char of_2[] = ",\"TgtNode\"";
11324 
11325  char d_flow_coeff[] = ",\"D(CL)\",\"D(CD)\",\"D(CSF)\",\"D(CMx)\",\"D(CMy)\",\"D(CMz)\",\"D(CFx)\",\"D(CFy)\",\"D(CFz)\",\"D(CL/CD)\",\"D(Custom_ObjFunc)\"";
11326 
11327  /*--- Header for the residuals ---*/
11328 
11329  char fsi_resid[]= ",\"Res_FSI\",\"RelaxCoeff\",\"ForceCoeff\"";
11330 
11331  char flow_resid[]= ",\"Res_BGS[F0]\",\"Res_BGS[F1]\",\"Res_BGS[F2]\",\"Res_BGS[F3]\",\"Res_BGS[F4]\"";
11332  char adj_flow_resid[]= ",\"Res_AdjFlow[0]\",\"Res_AdjFlow[1]\",\"Res_AdjFlow[2]\",\"Res_AdjFlow[3]\",\"Res_AdjFlow[4]\"";
11333  char fem_resid[]= ",\"Res_BGS[S0]\",\"Res_BGS[S1]\",\"Res_BGS[S2]\"";
11334 
11335  /*--- End of the header ---*/
11336 
11337  char end[]= ",\"Time(min)\"\n";
11338 
11339  if ((config[ZONE_FLOW]->GetOutput_FileFormat() == TECPLOT) ||
11340  (config[ZONE_FLOW]->GetOutput_FileFormat() == TECPLOT_BINARY) ||
11341  (config[ZONE_FLOW]->GetOutput_FileFormat() == FIELDVIEW) ||
11342  (config[ZONE_FLOW]->GetOutput_FileFormat() == FIELDVIEW_BINARY)) {
11343  FSIHist_file[0] << "TITLE = \"SU2 FSI Simulation\"" << endl;
11344  FSIHist_file[0] << "VARIABLES = ";
11345  }
11346 
11347  /*--- Write the header, case depending ---*/
11348 
11349  FSIHist_file[0] << begin;
11350 
11351  FSIHist_file[0] << fsi_resid;
11352 
11353  switch (config[ZONE_FLOW]->GetKind_Solver()) {
11354 
11355  /*--- Flow residual output ---*/
11356 
11357  case EULER : case NAVIER_STOKES: case RANS :
11358  FSIHist_file[0] << flow_resid;
11359  if (turbulent) FSIHist_file[0] << turb_resid;
11360  break;
11361 
11363  FSIHist_file[0] << adj_flow_resid;
11364  break;
11365 
11366  }
11367 
11368  /*--- FEA residual output ---*/
11369 
11370  switch (config[ZONE_STRUCT]->GetKind_Solver()) {
11371 
11372  case FEM_ELASTICITY:
11373  FSIHist_file[0] << fem_resid;
11374  break;
11375 
11376  case DISC_ADJ_FEM:
11377  FSIHist_file[0] << fem_resid ;
11378  break;
11379 
11380  }
11381 
11382  /*--- Flow coefficients output ---*/
11383  switch (config[ZONE_FLOW]->GetKind_Solver()) {
11384 
11385  case EULER : case NAVIER_STOKES: case RANS :
11386  FSIHist_file[0] << flow_coeff;
11387  if (turbulent) FSIHist_file[0] << turb_resid;
11388  if (direct_diff != NO_DERIVATIVE) {
11389  FSIHist_file[0] << d_flow_coeff;
11390  }
11391  break;
11392 
11394  FSIHist_file[0] << adj_flow_resid;
11395  break;
11396 
11397  }
11398 
11399  switch (config[ZONE_STRUCT]->GetKind_Solver()) {
11400 
11401  case FEM_ELASTICITY:
11402  FSIHist_file[0] << fem_coeff;
11403  break;
11404 
11405  case DISC_ADJ_FEM:
11406  FSIHist_file[0] << fem_coeff;
11407  break;
11408 
11409  }
11410 
11411  switch (config[ZONE_STRUCT]->GetKind_ObjFunc()){
11412  case REFERENCE_GEOMETRY:
11413  FSIHist_file[0] << of_1;
11414  break;
11415  case REFERENCE_NODE:
11416  FSIHist_file[0] << of_2;
11417  break;
11418  default:
11419  break;
11420  }
11421 
11422  FSIHist_file[0] << end;
11423 
11424 
11425  }
11426 
11427  if ((rank == MASTER_NODE) && (!header)){
11428 
11429  unsigned short nDim = geometry[ZONE_STRUCT][INST_0][MESH_0]->GetnDim();
11430 
11431  unsigned long iExtIter = config[ZONE_STRUCT]->GetExtIter();
11432  unsigned long ExtIter_OffSet = config[ZONE_STRUCT]->GetExtIter_OffSet();
11433  unsigned long iFSIIter = config[ZONE_STRUCT]->GetFSIIter();
11434  su2double dummy = 0.0;
11435 
11436  bool first_iter = ((iExtIter==0) && (iFSIIter == 0));
11437 
11438 
11439  bool compressible = (config[ZONE_FLOW]->GetKind_Regime() == COMPRESSIBLE);
11440  bool incompressible = (config[ZONE_FLOW]->GetKind_Regime() == INCOMPRESSIBLE);
11441 
11442 
11443  bool fem = ((config[ZONE_STRUCT]->GetKind_Solver() == FEM_ELASTICITY) ||
11444  (config[ZONE_STRUCT]->GetKind_Solver() == DISC_ADJ_FEM));
11445  bool linear_analysis = (config[ZONE_STRUCT]->GetGeometricConditions() == SMALL_DEFORMATIONS);
11446  bool nonlinear_analysis = (config[ZONE_STRUCT]->GetGeometricConditions() == LARGE_DEFORMATIONS);
11447 
11448  bool disc_adj_flow = config[ZONE_FLOW]->GetDiscrete_Adjoint();
11449  bool disc_adj_fem = config[ZONE_STRUCT]->GetDiscrete_Adjoint();
11450 
11451 
11452  /*--- WARNING: These buffers have hard-coded lengths. Note that you
11453  may have to adjust them to be larger if adding more entries. ---*/
11454 
11455  char begin[1000], direct_coeff[1000],
11456  fsi_resid[1000], fsi_coeffs[1000],
11457  flow_resid[1000], fem_resid[1000],
11458  objective_function[1000], end[1000];
11459 
11460  su2double *residual_flow = NULL;
11461  su2double *residual_fem = NULL;
11462  su2double *residual_fsi = NULL;
11463  su2double *coeffs_fsi = NULL;
11464 
11465  /*--- Initialize number of variables ---*/
11466  unsigned short nVar_FSI = 1, nCoeff_FSI = 2, nVar_Flow = 0, nVar_FEM = 0;
11467 
11468  unsigned short iVar;
11469 
11470  /*--- Direct problem variables ---*/
11471  if (compressible) nVar_Flow = nDim+2; else nVar_Flow = nDim+1;
11472 
11473  if (fem) {
11474  if (linear_analysis) nVar_FEM = nDim;
11475  if (nonlinear_analysis) nVar_FEM = 3;
11476  if (disc_adj_fem) nVar_FEM = nDim;
11477  }
11478 
11479  residual_flow = new su2double[nVar_Flow];
11480  residual_fem = new su2double[nVar_FEM];
11481  residual_fsi = new su2double[nVar_FSI];
11482  coeffs_fsi = new su2double[nCoeff_FSI];
11483 
11484  /*--- Initialize variables to store information from all domains (direct solution) ---*/
11485 
11486  su2double Total_CL = 0.0, Total_CD = 0.0, Total_CMx = 0.0, Total_CMy = 0.0, Total_CMz = 0.0, Total_CEff = 0.0,
11487  Total_OF = 0.0;
11488 
11489  Total_CL = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CL();
11490  Total_CD = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CD();
11491  Total_CEff = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CEff();
11492  Total_CMx = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CMx();
11493  Total_CMy = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CMy();
11494  Total_CMz = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetTotal_CMz();
11495 
11496  bool print_of = false;
11497 
11498  switch (config[ZONE_STRUCT]->GetKind_ObjFunc()){
11499  case REFERENCE_GEOMETRY:
11500  Total_OF = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetTotal_OFRefGeom();
11501  print_of = true;
11502  break;
11503  case REFERENCE_NODE:
11504  Total_OF = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetTotal_OFRefNode();
11505  print_of = true;
11506  break;
11507  default:
11508  break;
11509  }
11510 
11511  if ((!disc_adj_flow) && (!disc_adj_fem)){
11512  /*--- Flow Residuals ---*/
11513  for (iVar = 0; iVar < nVar_Flow; iVar++)
11514  residual_flow[iVar] = solver_container[ZONE_FLOW][INST_0][MESH_0][FLOW_SOL]->GetRes_BGS(iVar);
11515 
11516  /*--- FEA Residuals ---*/
11517  for (iVar = 0; iVar < nVar_FEM; iVar++)
11518  residual_fem[iVar] = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetRes_BGS(iVar);
11519 
11520  residual_fsi[0] = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetFSI_Residual();
11521  coeffs_fsi[0] = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetRelaxCoeff();
11522  coeffs_fsi[1] = solver_container[ZONE_STRUCT][INST_0][MESH_0][FEA_SOL]->GetForceCoeff();
11523 
11524  }
11525  else{
11526  /*--- Flow Residuals ---*/
11527  for (iVar = 0; iVar < nVar_Flow; iVar++)
11528  residual_flow[iVar] = solver_container[ZONE_FLOW][INST_0][MESH_0][ADJFLOW_SOL]->GetRes_BGS(iVar);
11529  /*--- FEA Residuals ---*/
11530  for (iVar = 0; iVar < nVar_FEM; iVar++)
11531  residual_fem[iVar] = solver_container[ZONE_STRUCT][INST_0][MESH_0][ADJFEA_SOL]->GetRes_BGS(iVar);
11532  }
11533 
11534  /*--- Write the begining of the history file ---*/
11535  SPRINTF(begin, "%12d, %12d", SU2_TYPE::Int(iExtIter+ExtIter_OffSet), SU2_TYPE::Int(iFSIIter));
11536  /*--- Write the end of the history file ---*/
11537  SPRINTF (end, "\n");
11538 
11539  SPRINTF (fsi_resid, ", %14.8e", log10 (residual_fsi[0]));
11540  SPRINTF (fsi_coeffs, ", %14.8e, %14.8e", coeffs_fsi[0], coeffs_fsi[1]);
11541 
11542  /*--- Flow residual ---*/
11543  if (nDim == 2) {
11544  if (compressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), dummy);
11545  if (incompressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), dummy, dummy);
11546  }
11547  else {
11548  if (compressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), log10 (residual_flow[4]) );
11549  if (incompressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), dummy);
11550  }
11551 
11552  /*--- FEM residual ---*/
11553  if (nDim == 2) SPRINTF (fem_resid, ", %14.8e, %14.8e, %14.8e", log10 (residual_fem[0]), log10 (residual_fem[1]), dummy);
11554  else SPRINTF (fem_resid, ", %14.8e, %14.8e, %14.8e", log10 (residual_fem[0]), log10 (residual_fem[1]), log10 (residual_fem[1]));
11555 
11556  /*--- Direct coefficients ---*/
11557  SPRINTF (direct_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e",Total_CL, Total_CD, Total_CMx, Total_CMy, Total_CMz, Total_CEff);
11558 
11559  if (print_of) SPRINTF (objective_function, ", %14.8e", Total_OF);
11560 
11561  if (!first_iter){
11562  if (!print_of) FSIHist_file[0] << begin << fsi_resid << fsi_coeffs << flow_resid << fem_resid << direct_coeff << end;
11563  else FSIHist_file[0] << begin << fsi_resid << fsi_coeffs << flow_resid << fem_resid << direct_coeff << objective_function << end;
11564  FSIHist_file[0].flush();
11565  }
11566 
11567  delete [] residual_flow;
11568  delete [] residual_fem;
11569  delete [] residual_fsi;
11570  delete [] coeffs_fsi;
11571 
11572 
11573  }
11574 
11575 }
11576 
11577 void COutput::SetSensitivity_Files(CGeometry **geometry, CConfig **config, unsigned short val_nZone) {
11578 
11579  unsigned short iMarker,iDim, nDim, iVar, nMarker, nVar;
11580  unsigned long iVertex, iPoint, nPoint, nVertex;
11581  su2double *Normal, Prod, Sens = 0.0, SensDim, Area;
11582 
11583  unsigned short iZone;
11584 
11585  CSolver **solver = new CSolver*[val_nZone];
11586 
11587  for (iZone = 0; iZone < val_nZone; iZone++) {
11588 
11589 
11590  nPoint = geometry[iZone]->GetnPoint();
11591  nDim = geometry[iZone]->GetnDim();
11592  nMarker = config[iZone]->GetnMarker_All();
11593  nVar = nDim + 1;
11594 
11595  /*--- We create a baseline solver to easily merge the sensitivity information ---*/
11596 
11597  vector<string> fieldnames;
11598  fieldnames.push_back("\"Point\"");
11599  fieldnames.push_back("\"x\"");
11600  fieldnames.push_back("\"y\"");
11601  if (nDim == 3) {
11602  fieldnames.push_back("\"z\"");
11603  }
11604  fieldnames.push_back("\"Sensitivity_x\"");
11605  fieldnames.push_back("\"Sensitivity_y\"");
11606  if (nDim == 3) {
11607  fieldnames.push_back("\"Sensitivity_z\"");
11608  }
11609  fieldnames.push_back("\"Surface_Sensitivity\"");
11610 
11611  solver[iZone] = new CBaselineSolver(geometry[iZone], config[iZone], nVar+nDim, fieldnames);
11612 
11613  for (iPoint = 0; iPoint < nPoint; iPoint++) {
11614  for (iDim = 0; iDim < nDim; iDim++) {
11615  solver[iZone]->node[iPoint]->SetSolution(iDim, geometry[iZone]->node[iPoint]->GetCoord(iDim));
11616  }
11617  for (iVar = 0; iVar < nDim; iVar++) {
11618  solver[iZone]->node[iPoint]->SetSolution(iVar+nDim, geometry[iZone]->GetSensitivity(iPoint, iVar));
11619  }
11620  }
11621 
11622  /*--- Compute the sensitivity in normal direction ---*/
11623 
11624  for (iMarker = 0; iMarker < nMarker; iMarker++) {
11625 
11626  if((config[iZone]->GetMarker_All_KindBC(iMarker) == HEAT_FLUX ) ||
11627  (config[iZone]->GetMarker_All_KindBC(iMarker) == EULER_WALL ) ||
11628  (config[iZone]->GetMarker_All_KindBC(iMarker) == TRANSPIRATION ) ||
11629  (config[iZone]->GetMarker_All_KindBC(iMarker) == ISOTHERMAL )) {
11630 
11631  nVertex = geometry[iZone]->GetnVertex(iMarker);
11632 
11633  for (iVertex = 0; iVertex < nVertex; iVertex++) {
11634  iPoint = geometry[iZone]->vertex[iMarker][iVertex]->GetNode();
11635  Normal = geometry[iZone]->vertex[iMarker][iVertex]->GetNormal();
11636  Prod = 0.0;
11637  Area = 0.0;
11638  for (iDim = 0; iDim < nDim; iDim++) {
11639 
11640  /*--- Retrieve the gradient calculated with discrete adjoint method ---*/
11641 
11642  SensDim = geometry[iZone]->GetSensitivity(iPoint, iDim);
11643 
11644  /*--- Calculate scalar product for projection onto the normal vector ---*/
11645 
11646  Prod += Normal[iDim]*SensDim;
11647 
11648  Area += Normal[iDim]*Normal[iDim];
11649  }
11650 
11651  Area = sqrt(Area);
11652 
11653  /*--- Projection of the gradient onto the normal vector of the surface ---*/
11654 
11655  Sens = Prod/Area;
11656 
11657  solver[iZone]->node[iPoint]->SetSolution(2*nDim, Sens);
11658 
11659  }
11660  }
11661  }
11662  }
11663 
11664  /*--- Merge the information and write the output files ---*/
11665 
11666  SetBaselineResult_Files(&solver, &geometry, config, 0, val_nZone);
11667 
11668  for (iZone = 0; iZone < val_nZone; iZone++) {
11669  delete solver[iZone];
11670  }
11671  delete [] solver;
11672 }
11673 
11675 
11676  unsigned short iMarker_Monitoring;
11677  string inMarker_Tag, outMarker_Tag, inMarkerTag_Mix;
11678  unsigned short nZone = config->GetnZone();
11679  bool turbulent = ((config->GetKind_Solver() == RANS) || (config->GetKind_Solver() == DISC_ADJ_RANS));
11680  bool menter_sst = (config->GetKind_Turb_Model() == SST);
11681 
11682  unsigned short nBladesRow, nStages;
11683  unsigned short iStage;
11684  nBladesRow = config->GetnMarker_Turbomachinery();
11685  nStages = SU2_TYPE::Int(nBladesRow/2);
11686 
11687  cout << endl << "------------------------- Turbomachinery Summary ------------------------" << endl;
11688  cout << endl;
11689  for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Turbomachinery(); iMarker_Monitoring++){
11690  cout << endl << "----------------------------- Blade " << iMarker_Monitoring + 1 << " -----------------------------------" << endl;
11691  inMarker_Tag = config->GetMarker_TurboPerf_BoundIn(iMarker_Monitoring);
11692  outMarker_Tag = config->GetMarker_TurboPerf_BoundOut(iMarker_Monitoring);
11693  if(iMarker_Monitoring == 0){
11694  cout << "BC Inlet convergence monitoring marker " << inMarker_Tag << " : "<<endl;
11695  cout << endl;
11696  cout << " Inlet Total Enthalpy" << " Inlet Total Enthalpy BC" << " err(%)" << endl;
11697  cout.width(25); cout << TotalEnthalpyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref();
11698  cout.width(25); cout << TotalEnthalpyIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref();
11699  cout.width(25); cout << abs((TotalEnthalpyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - TotalEnthalpyIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/TotalEnthalpyIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])*100.0;
11700  cout << endl;
11701  cout << endl;
11702  cout << " Inlet Entropy" << " Inlet Entropy BC" << " err(%)" << endl;
11703  cout.width(25); cout << EntropyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref()/config->GetTemperature_Ref();
11704  cout.width(25); cout << EntropyIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref()/config->GetTemperature_Ref();
11705  cout.width(25); cout << abs((EntropyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - EntropyIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/EntropyIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])*100.0;
11706  cout << endl;
11707  cout << endl;
11708  cout << " Inlet Absolute Angle" << " Inlet Absolute Angle BC" << " err(%)" << endl;
11709  cout.width(25); cout << 180.0/PI_NUMBER*AbsFlowAngleIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11710  cout.width(25); cout << 180.0/PI_NUMBER*FlowAngleIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11711  cout.width(25); cout << abs((AbsFlowAngleIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - FlowAngleIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/FlowAngleIn_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])*100.0;
11712  cout << endl;
11713  cout << endl;
11714  if(turbulent){
11715  if(menter_sst){
11716  cout << " Inlet TurbIntensity" << " Inlet TurbIntensity BC" << " err(%)" << endl;
11717  cout.width(25); cout << TurbIntensityIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11718  cout.width(25); cout << config->GetTurbulenceIntensity_FreeStream();
11719  cout.width(25); cout << abs((TurbIntensityIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - config->GetTurbulenceIntensity_FreeStream())/config->GetTurbulenceIntensity_FreeStream())*100.0;
11720  cout << endl;
11721  cout << endl;
11722  cout << " Inlet Turb2LamRatio" << " Inlet Turb2LamRatio BC" << " err(%)" << endl;
11723  cout.width(25); cout << Turb2LamViscRatioIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11724  cout.width(25); cout << config->GetTurb2LamViscRatio_FreeStream();
11725  cout.width(25); cout << abs((Turb2LamViscRatioIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - config->GetTurb2LamViscRatio_FreeStream())/config->GetTurb2LamViscRatio_FreeStream())*100.0;
11726  cout << endl;
11727  cout << endl;
11728  }
11729  else{
11730  cout << " Inlet Nu Factor" << " Inlet Nu Factor BC" << " err(%)" << endl;
11731  cout.width(25); cout << NuFactorIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11732  cout.width(25); cout << config->GetNuFactor_FreeStream();
11733  cout.width(25); cout << abs((NuFactorIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - config->GetNuFactor_FreeStream())/config->GetNuFactor_FreeStream())*100.0;
11734  cout << endl;
11735  cout << endl;
11736  }
11737  }
11738  }
11739  if(iMarker_Monitoring == config->GetnMarker_Turbomachinery() -1 ){
11740  // if BC outlet
11741  cout << "BC outlet convergence monitoring marker " << outMarker_Tag << " : "<<endl;
11742  cout << endl;
11743  cout << " Outlet Pressure" << " Outlet Pressure BC" << " err(%)" << endl;
11744  cout.width(25); cout << PressureOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetPressure_Ref();
11745  cout.width(25); cout << PressureOut_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetPressure_Ref();
11746  cout.width(25); cout << abs((PressureOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - PressureOut_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/PressureOut_BC[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])*100.0;
11747  cout << endl;
11748  cout << endl;
11749  }
11750 
11751  cout << "Convergence monitoring for integral quantities between markers " << inMarker_Tag << " and "<< outMarker_Tag << " : "<<endl;
11752  cout << endl;
11753  cout << " Inlet Mass Flow " << " Outlet Mass Flow" << " err(%)" << endl;
11754  cout.width(25); cout << MassFlowIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetVelocity_Ref()*config->GetDensity_Ref();
11755  cout.width(25); cout << MassFlowOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetVelocity_Ref()*config->GetDensity_Ref();
11756  cout.width(25); cout << abs((MassFlowIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - MassFlowOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/MassFlowIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])*100.0;
11757  cout << endl;
11758  cout << endl;
11759  //if(stator)
11760  //cout << " Inlet Total Enthalpy " << " Outlet Total Enthalpy" << " err(%)" << endl;
11761  //else
11762  cout << " Inlet Total Rothalpy " << " Outlet Total Rothalpy" << " err(%)" << endl;
11763  cout.width(25); cout << RothalpyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref();
11764  cout.width(25); cout << RothalpyOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref();
11765  cout.width(25); cout << abs((RothalpyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)] - RothalpyOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/RothalpyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])*100.0;
11766  cout << endl;
11767  cout << endl;
11768  cout << "Blade performance between boundaries " << inMarker_Tag << " and "<< outMarker_Tag << " : "<<endl;
11769  cout << endl;
11770  cout << " Total Pressure Loss(%)" << " Kinetic Energy Loss(%)" << " Entropy Generation(%)" << endl;
11771  cout.width(25); cout << TotalPressureLoss[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*100.0;
11772  cout.width(25); cout << KineticEnergyLoss[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*100.0;
11773  cout.width(25); cout << EntropyGen[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*100.0;
11774  cout << endl;
11775  cout << endl;
11776  cout << " Total Inlet Enthalpy" << " Eulerian Work" << " Pressure Ratio" << endl;
11777  cout.width(25); cout << TotalEnthalpyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref();
11778  cout.width(25); cout << EulerianWork[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref();
11779  cout.width(25); cout << PressureRatio[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11780  cout << endl;
11781  cout << endl;
11782  cout << " Inlet Entropy" << " Outlet Entropy" << " Outlet Is. Enthalpy" << endl;
11783  cout.width(25); cout << EntropyIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref()/config->GetTemperature_Ref();
11784  cout.width(25); cout << EntropyOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref()/config->GetTemperature_Ref();
11785  cout.width(25); cout << EnthalpyOutIs[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref();
11786  cout << endl;
11787  cout << endl;
11788  cout << "Cinematic quantities between boundaries " << inMarker_Tag << " and "<< outMarker_Tag << " : "<<endl;
11789  cout << endl;
11790  cout << " Inlet Mach"<< " Inlet Normal Mach" << " Inlet Tang. Mach" << endl;
11791  cout.width(25); cout << sqrt(MachIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][0]*MachIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][0] +MachIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][1]*MachIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][1]);
11792  cout.width(25); cout << MachIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][0];
11793  cout.width(25); cout << MachIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][1];
11794  cout << endl;
11795  cout << endl;
11796  cout << " Outlet Mach"<< " Outlet Normal Mach" << " Outlet Tang. Mach" << endl;
11797  cout.width(25); cout << sqrt(MachOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][0]*MachOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][0] +MachOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][1]*MachOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][1]);
11798  cout.width(25); cout << MachOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][0];
11799  cout.width(25); cout << MachOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][1];cout << endl;
11800  cout << endl;
11801  cout << " Inlet Flow Angle" << " Outlet flow Angle " << endl;
11802  cout.width(25); cout << 180.0/PI_NUMBER*FlowAngleIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11803  cout.width(25); cout << 180.0/PI_NUMBER*FlowAngleOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11804  cout << endl;
11805  cout << endl;
11806  // if gridmov
11807  cout << " Inlet Abs Flow Angle" << " Outlet Abs Flow Angle " << endl;
11808  cout.width(25); cout << 180.0/PI_NUMBER*AbsFlowAngleIn[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11809  cout.width(25); cout << 180.0/PI_NUMBER*AbsFlowAngleOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11810  cout << endl;
11811  cout << endl << "-------------------------------------------------------------------------" << endl;
11812  cout << endl;
11813  if(nZone > 0 && iMarker_Monitoring < config->GetnMarker_Turbomachinery() -1){
11814  cout << endl << "---------- Mixing-Plane Interface between Blade " << iMarker_Monitoring + 1 << " and Blade " << iMarker_Monitoring + 2 << " -----------" << endl;
11815  cout << endl;
11816  inMarkerTag_Mix = config->GetMarker_TurboPerf_BoundIn(iMarker_Monitoring + 1);
11817  cout << "Convergence monitoring for the outlet " << outMarker_Tag << " and the inlet "<< inMarkerTag_Mix << " : "<<endl;
11818  cout << endl;
11819  cout << " Outlet Density " << " Inlet Density" << " err(%)" << endl;
11820  cout.width(25); cout << DensityOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetDensity_Ref();
11821  cout.width(25); cout << DensityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring + 1)]*config->GetDensity_Ref();
11822  cout.width(25); cout << abs((DensityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)] - DensityOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/DensityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)])*100.0;
11823  cout << endl;
11824  cout << endl;
11825  cout << " Outlet Pressure " << " Inlet Pressure" << " err(%)" << endl;
11826  cout.width(25); cout << PressureOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetPressure_Ref();
11827  cout.width(25); cout << PressureIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)]*config->GetPressure_Ref();
11828  cout.width(25); cout << abs((PressureIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)] - PressureOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/PressureIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)])*100.0;
11829  cout << endl;
11830  cout << endl;
11831  cout << " Outlet Normal Velocity " << " Inlet Normal Velocity" << " err(%)" << endl;
11832  cout.width(25); cout << TurboVelocityOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][0]*config->GetVelocity_Ref();
11833  cout.width(25); cout << TurboVelocityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)][0]*config->GetVelocity_Ref();
11834  cout.width(25); cout << abs((TurboVelocityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)][0] - TurboVelocityOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][0])/TurboVelocityIn[iMarker_Monitoring+1][config->GetnSpan_iZones(iMarker_Monitoring +1)][0])*100.0;
11835  cout << endl;
11836  cout << endl;
11837  cout << " Outlet Tang. Velocity " << " Inlet Tang. Velocity" << " err(%)" << endl;
11838  cout.width(25); cout << TurboVelocityOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][1]*config->GetVelocity_Ref();
11839  cout.width(25); cout << TurboVelocityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)][1]*config->GetVelocity_Ref();
11840  cout.width(25); cout << abs((TurboVelocityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)][1] - TurboVelocityOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)][1])/TurboVelocityIn[iMarker_Monitoring+1][config->GetnSpan_iZones(iMarker_Monitoring +1)][1])*100.0;
11841  cout << endl;
11842  cout << endl;
11843  cout << " Outlet Entropy " << " Inlet Entropy" << " err(%)" << endl;
11844  cout.width(25); cout << EntropyOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)]*config->GetEnergy_Ref()/config->GetTemperature_Ref();
11845  cout.width(25); cout << EntropyIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)]*config->GetEnergy_Ref()/config->GetTemperature_Ref();
11846  cout.width(25); cout << abs((EntropyIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring+1)] - EntropyOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/EntropyIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring+1)])*100.0;
11847  if(turbulent){
11848  cout << endl;
11849  cout << endl;
11850  if(menter_sst){
11851  cout << " Outlet TurbIntensity " << " Inlet TurbIntensity" << " err(%)" << endl;
11852  cout.width(25); cout << TurbIntensityOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11853  cout.width(25); cout << TurbIntensityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)];
11854  cout.width(25); cout << abs((TurbIntensityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring+1)] - TurbIntensityOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/TurbIntensityIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring+1)])*100.0;
11855  cout << endl;
11856  cout << endl;
11857  cout << " Outlet Turb2LamRatio " << " Inlet Turb2LamRatio" << " err(%)" << endl;
11858  cout.width(25); cout << Turb2LamViscRatioOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11859  cout.width(25); cout << Turb2LamViscRatioIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)];
11860  cout.width(25); cout << abs((Turb2LamViscRatioIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring+1)] - Turb2LamViscRatioOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/Turb2LamViscRatioIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring+1)])*100.0;
11861  }
11862  else{
11863  cout << " Outlet Nu Factor " << " Inlet Nu Factor" << " err(%)" << endl;
11864  cout.width(25); cout << NuFactorOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)];
11865  cout.width(25); cout << NuFactorIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring +1)];
11866  cout.width(25); cout << abs((NuFactorIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring+1)] - NuFactorOut[iMarker_Monitoring][config->GetnSpan_iZones(iMarker_Monitoring)])/NuFactorIn[iMarker_Monitoring + 1][config->GetnSpan_iZones(iMarker_Monitoring+1)])*100.0;
11867  }
11868  }
11869  cout << endl;
11870  cout << endl << "-------------------------------------------------------------------------" << endl;
11871  cout << endl;
11872  }
11873 
11874  }
11875  if(nZone > 1){
11876  /*--- Stage Performance ---*/
11877  for(iStage = 0; iStage < nStages; iStage++ ){
11878  cout << endl << "----------------------------- Stage " << iStage + 1 << " -----------------------------------" << endl;
11879  inMarker_Tag = config->GetMarker_TurboPerf_BoundIn(iStage*2);
11880  outMarker_Tag = config->GetMarker_TurboPerf_BoundOut(iStage*2+1);
11881  cout << "Stage performance between boundaries " << inMarker_Tag << " and "<< outMarker_Tag << " : "<<endl;
11882  cout << endl;
11883  cout << " Total-Total Eff.(%)" << " Total-Static Eff.(%)" << " Entropy Generation(%)" << endl;
11884  cout.width(25); cout << TotalTotalEfficiency[nBladesRow + iStage][nSpanWiseSections]*100.0;
11885  cout.width(25); cout << TotalStaticEfficiency[nBladesRow + iStage][nSpanWiseSections]*100.0;
11886  cout.width(25); cout << EntropyGen[nBladesRow + iStage][nSpanWiseSections]*100.0;
11887  cout << endl;
11888  cout << endl;
11889  cout << " Pressure Ratio " << " Outlet Is. Enthalpy" << " In-Out MassFlow Diff (%)" << endl;
11890  cout.width(25); cout << PressureRatio[nBladesRow + iStage][nSpanWiseSections];
11891  cout.width(25); cout << EnthalpyOutIs[nBladesRow + iStage][nSpanWiseSections]*config->GetEnergy_Ref();
11892  cout.width(25); cout << abs((MassFlowIn[nBladesRow + iStage][nSpanWiseSections] - MassFlowOut[nBladesRow + iStage][nSpanWiseSections])/MassFlowIn[nBladesRow + iStage][nSpanWiseSections])*100.0;
11893  }
11894  cout << endl;
11895  cout << endl << "-------------------------------------------------------------------------" << endl;
11896  cout << endl;
11897 
11898  /*--- Full Machine Performance ---*/
11899  // if(turbine)
11900  cout << endl << "---------------------------- Turbine ------------------------------------" << endl;
11901  inMarker_Tag = config->GetMarker_TurboPerf_BoundIn(0);
11902  outMarker_Tag = config->GetMarker_TurboPerf_BoundOut(nBladesRow-1);
11903  cout << "Turbine performance between boundaries " << inMarker_Tag << " and "<< outMarker_Tag << " : "<<endl;
11904  cout << endl;
11905  cout << " Total-Total Eff.(%)" << " Total-Static Eff.(%)" << " Entropy Generation(%)" << endl;
11906  cout.width(25); cout << TotalTotalEfficiency[nBladesRow + nStages][nSpanWiseSections]*100.0;
11907  cout.width(25); cout << TotalStaticEfficiency[nBladesRow + nStages][nSpanWiseSections]*100.0;
11908  cout.width(25); cout << EntropyGen[nBladesRow + nStages][nSpanWiseSections]*100.0;
11909  cout << endl;
11910  cout << endl;
11911  cout << " Pressure Ratio " << " Outlet Is. Enthalpy" << " In-Out MassFlow Diff (%)" << endl;
11912  cout.width(25); cout << PressureRatio[nBladesRow + nStages][nSpanWiseSections];
11913  cout.width(25); cout << EnthalpyOutIs[nBladesRow + nStages][nSpanWiseSections]*config->GetEnergy_Ref();;
11914  cout.width(25); cout << abs((MassFlowIn[nBladesRow + nStages][nSpanWiseSections] - MassFlowOut[nBladesRow + nStages][nSpanWiseSections])/MassFlowIn[nBladesRow + nStages][nSpanWiseSections])*100.0;
11915  cout << endl;
11916  cout << endl << "-------------------------------------------------------------------------" << endl;
11917  cout << endl;
11918  }
11919 
11920 }
11921 
11922 void COutput::SpecialOutput_Turbo(CSolver *****solver, CGeometry ****geometry, CConfig **config,
11923  unsigned short val_iZone, bool output) {
11924 
11925  string inMarker_Tag, outMarker_Tag, inMarkerTag_Mix;
11926  unsigned short nZone = config[val_iZone]->GetnZone();
11927 
11928  unsigned short iDim, iSpan;
11929 
11930  unsigned long iExtIter = config[val_iZone]->GetExtIter();
11931  su2double* SpanWiseValuesIn, *SpanWiseValuesOut;
11932  ofstream myfile;
11933  string spanwise_performance_filename;
11934 
11935 
11936  /*--- Start of write file turboperformance spanwise ---*/
11937  if (rank == MASTER_NODE){
11938  SpanWiseValuesIn = geometry[val_iZone][INST_0][MESH_0]->GetSpanWiseValue(1);
11939  SpanWiseValuesOut = geometry[val_iZone][INST_0][MESH_0]->GetSpanWiseValue(2);
11940 
11941 
11942 
11943  /*--- Writing Span wise inflow thermodynamic quantities. ---*/
11944  spanwise_performance_filename = "TURBOMACHINERY/inflow_spanwise_thermodynamic_values.dat";
11945  char buffer[50];
11946  if (nZone > 1){
11947  unsigned short lastindex = spanwise_performance_filename.find_last_of(".");
11948  spanwise_performance_filename = spanwise_performance_filename.substr(0, lastindex);
11949  SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(val_iZone));
11950  spanwise_performance_filename.append(string(buffer));
11951  }
11952 
11953 
11954  myfile.open (spanwise_performance_filename.data(), ios::out | ios::trunc);
11955  myfile.setf(ios::scientific);
11956  myfile.precision(12);
11957 
11958  myfile << "TITLE = \"Inflow Spanwise Thermodynamic Values. iExtIter = " << iExtIter << " \"" << endl;
11959  myfile << "VARIABLES =" << endl;
11960 
11961  myfile.width(30); myfile << "\"SpanWise Value[m]\"";
11962  myfile.width(15); myfile << "\"iSpan\"";
11963  myfile.width(30); myfile << "\"Pressure[Pa]\"";
11964  myfile.width(30); myfile << "\"TotalPressure[Pa]\"";
11965  myfile.width(30); myfile << "\"Temperature[K]\"";
11966  myfile.width(30); myfile << "\"TotalTemperature[K]\"";
11967  myfile.width(30); myfile << "\"Enthalpy[J]\"";
11968  myfile.width(30); myfile << "\"TotalEnthalpy[J]\"";
11969  myfile.width(30); myfile << "\"Density[kg/m3]\"";
11970  myfile.width(30); myfile << "\"Entropy[J/K]\"";
11971  myfile.width(30); myfile << "\"TurbIntensity[-]\"";
11972  myfile.width(30); myfile << "\"Turb2LamViscRatio[-]\"";
11973  myfile.width(30); myfile << "\"NuFactor[-]\"";
11974  myfile << endl;
11975 
11976  for(iSpan = 0; iSpan < config[ZONE_0]->GetnSpan_iZones(val_iZone); iSpan++){
11977 
11978  myfile.width(30); myfile << SpanWiseValuesIn[iSpan];
11979  myfile.width(15); myfile << iSpan;
11980  myfile.width(30); myfile << PressureIn [val_iZone][iSpan]*config[ZONE_0]->GetPressure_Ref();
11981  myfile.width(30); myfile << TotalPressureIn [val_iZone][iSpan]*config[ZONE_0]->GetPressure_Ref();
11982  myfile.width(30); myfile << TemperatureIn [val_iZone][iSpan]*config[ZONE_0]->GetTemperature_Ref();
11983  myfile.width(30); myfile << TotalTemperatureIn [val_iZone][iSpan]*config[ZONE_0]->GetTemperature_Ref();
11984  myfile.width(30); myfile << EnthalpyIn [val_iZone][iSpan]*config[ZONE_0]->GetEnergy_Ref();
11985  myfile.width(30); myfile << TotalEnthalpyIn [val_iZone][iSpan]*config[ZONE_0]->GetEnergy_Ref();
11986  myfile.width(30); myfile << DensityIn [val_iZone][iSpan]*config[ZONE_0]->GetDensity_Ref();
11987  myfile.width(30); myfile << EntropyIn [val_iZone][iSpan]*config[ZONE_0]->GetEnergy_Ref()/config[ZONE_0]->GetTemperature_Ref();
11988  if(TurbIntensityIn[val_iZone][iSpan] > 1.0){
11989  myfile.width(30); myfile << TurbIntensityIn [val_iZone][config[ZONE_0]->GetnSpan_iZones(val_iZone)/2];
11990  }else{
11991  myfile.width(30); myfile << TurbIntensityIn [val_iZone][iSpan];
11992  }
11993  myfile.width(30); myfile << Turb2LamViscRatioIn [val_iZone][iSpan];
11994  myfile.width(30); myfile << NuFactorIn [val_iZone][iSpan];
11995  myfile << endl;
11996  }
11997 
11998  myfile.close();
11999 
12000  /*--- Writing Span wise outflow thermodynamic quantities. ---*/
12001  spanwise_performance_filename = "TURBOMACHINERY/outflow_spanwise_thermodynamic_values.dat";
12002  if (nZone > 1){
12003  unsigned short lastindex = spanwise_performance_filename.find_last_of(".");
12004  spanwise_performance_filename = spanwise_performance_filename.substr(0, lastindex);
12005  SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(val_iZone));
12006  spanwise_performance_filename.append(string(buffer));
12007  }
12008 
12009  myfile.open (spanwise_performance_filename.data(), ios::out | ios::trunc);
12010  myfile.setf(ios::scientific);
12011  myfile.precision(12);
12012 
12013  myfile << "TITLE = \"Outflow Span-wise Thermodynamic Values. iExtIter = " << iExtIter << " \"" << endl;
12014  myfile << "VARIABLES =" << endl;
12015 
12016  myfile.width(30); myfile << "\"SpanWise Value[m]\"";
12017  myfile.width(15); myfile << "\"iSpan\"";
12018  myfile.width(30); myfile << "\"Pressure[Pa]\"";
12019  myfile.width(30); myfile << "\"TotalPressure[Pa]\"";
12020  myfile.width(30); myfile << "\"Temperature[K]\"";
12021  myfile.width(30); myfile << "\"TotalTemperature[K]\"";
12022  myfile.width(30); myfile << "\"Enthalpy[J]\"";
12023  myfile.width(30); myfile << "\"TotalEnthalpy[J]\"";
12024  myfile.width(30); myfile << "\"Density[kg/m3]\"";
12025  myfile.width(30); myfile << "\"Entropy[J/K]\"";
12026  myfile.width(30); myfile << "\"TurbIntensity[-]\"";
12027  myfile.width(30); myfile << "\"Turb2LamViscRatio[-]\"";
12028  myfile.width(30); myfile << "\"NuFactor[-]\"";
12029  myfile << endl;
12030 
12031 
12032  for(iSpan = 0; iSpan < config[ZONE_0]->GetnSpan_iZones(val_iZone); iSpan++){
12033 
12034  myfile.width(30); myfile << SpanWiseValuesOut[iSpan];
12035  myfile.width(15); myfile << iSpan;
12036  myfile.width(30); myfile << PressureOut [val_iZone][iSpan]*config[ZONE_0]->GetPressure_Ref();
12037  myfile.width(30); myfile << TotalPressureOut [val_iZone][iSpan]*config[ZONE_0]->GetPressure_Ref();
12038  myfile.width(30); myfile << TemperatureOut [val_iZone][iSpan]*config[ZONE_0]->GetTemperature_Ref();
12039  myfile.width(30); myfile << TotalTemperatureOut [val_iZone][iSpan]*config[ZONE_0]->GetTemperature_Ref();
12040  myfile.width(30); myfile << EnthalpyOut [val_iZone][iSpan]*config[ZONE_0]->GetEnergy_Ref();
12041  myfile.width(30); myfile << TotalEnthalpyOut [val_iZone][iSpan]*config[ZONE_0]->GetEnergy_Ref();
12042  myfile.width(30); myfile << DensityOut [val_iZone][iSpan]*config[ZONE_0]->GetDensity_Ref();
12043  myfile.width(30); myfile << EntropyOut [val_iZone][iSpan]*config[ZONE_0]->GetEnergy_Ref()/config[ZONE_0]->GetTemperature_Ref();
12044  if(TurbIntensityOut[val_iZone][iSpan] > 1.0){
12045  myfile.width(30); myfile << TurbIntensityOut [val_iZone][config[ZONE_0]->GetnSpan_iZones(val_iZone)/2];
12046  }else{
12047  myfile.width(30); myfile << TurbIntensityOut [val_iZone][iSpan];
12048  }
12049  myfile.width(30); myfile << Turb2LamViscRatioOut [val_iZone][iSpan];
12050  myfile.width(30); myfile << NuFactorOut [val_iZone][iSpan];
12051  myfile << endl;
12052  }
12053 
12054  myfile.close();
12055 
12056  /*--- Writing Span wise inflow kinematic quantities. ---*/
12057  spanwise_performance_filename = "TURBOMACHINERY/inflow_spanwise_kinematic_values.dat";
12058  if (nZone > 1){
12059  unsigned short lastindex = spanwise_performance_filename.find_last_of(".");
12060  spanwise_performance_filename = spanwise_performance_filename.substr(0, lastindex);
12061  SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(val_iZone));
12062  spanwise_performance_filename.append(string(buffer));
12063  }
12064 
12065  myfile.open (spanwise_performance_filename.data(), ios::out | ios::trunc);
12066  myfile.setf(ios::scientific);
12067  myfile.precision(12);
12068 
12069  myfile << "TITLE = \"Inflow Span-wise Kinematic Values. iExtIter = " << iExtIter << " \"" << endl;
12070  myfile << "VARIABLES =" << endl;
12071 
12072  myfile.width(30); myfile << "\"SpanWise Value[m]\"";
12073  myfile.width(15); myfile << "\"iSpan\"";
12074  myfile.width(30); myfile << "\"Normal Mach[-]\"";
12075  myfile.width(30); myfile << "\"Tangential Mach[-]\"";
12076  myfile.width(30); myfile << "\"3rd Component Mach[-]\"";
12077  myfile.width(30); myfile << "\"Mach Module[-]\"";
12078  myfile.width(30); myfile << "\"Normal Velocity[m/s]\"";
12079  myfile.width(30); myfile << "\"Tangential Velocity[m/s]\"";
12080  myfile.width(30); myfile << "\"3rd Component Velocity[m/s]\"";
12081  myfile.width(30); myfile << "\"Velocity Module[m/s]\"";
12082  myfile.width(30); myfile << "\"Absolute Flow Angle[deg]\"";
12083  myfile.width(30); myfile << "\"Relative Flow Angle[deg]\"";
12084  myfile << endl;
12085 
12086 
12087  for(iSpan = 0; iSpan < config[ZONE_0]->GetnSpan_iZones(val_iZone); iSpan++){
12088 
12089  myfile.width(30); myfile << SpanWiseValuesIn[iSpan];
12090  myfile.width(15); myfile << iSpan;
12091  for (iDim = 0; iDim < 4; iDim++){
12092  myfile.width(30); myfile << MachIn [val_iZone][iSpan][iDim];
12093  }
12094  for (iDim = 0; iDim < 4; iDim++){
12095  myfile.width(30); myfile << TurboVelocityIn [val_iZone][iSpan][iDim]*config[ZONE_0]->GetVelocity_Ref();
12096  }
12097  if(AbsFlowAngleIn[val_iZone][iSpan] != AbsFlowAngleIn[val_iZone][iSpan]){
12098  myfile.width(30); myfile << "0.0000";
12099  }
12100  else{
12101  myfile.width(30); myfile << AbsFlowAngleIn [val_iZone][iSpan]*180.0/PI_NUMBER;
12102  }
12103  if(FlowAngleIn[val_iZone][iSpan] != FlowAngleIn[val_iZone][iSpan]){
12104  myfile.width(30); myfile << "0.0000";
12105  }
12106  else{
12107  myfile.width(30); myfile << FlowAngleIn [val_iZone][iSpan]*180.0/PI_NUMBER;
12108  }
12109  myfile << endl;
12110  }
12111 
12112  myfile.close();
12113 
12114  /*--- Writing Span wise outflow thermodynamic quantities. ---*/
12115  spanwise_performance_filename = "TURBOMACHINERY/outflow_spanwise_kinematic_values.dat";
12116  if (nZone > 1){
12117  unsigned short lastindex = spanwise_performance_filename.find_last_of(".");
12118  spanwise_performance_filename = spanwise_performance_filename.substr(0, lastindex);
12119  SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(val_iZone));
12120  spanwise_performance_filename.append(string(buffer));
12121  }
12122 
12123  myfile.open (spanwise_performance_filename.data(), ios::out | ios::trunc);
12124  myfile.setf(ios::scientific);
12125  myfile.precision(12);
12126 
12127  myfile << "TITLE = \"Outflow Span-wise Kinematic Values. iExtIter = " << iExtIter << " \"" << endl;
12128  myfile << "VARIABLES =" << endl;
12129 
12130  myfile.width(30); myfile << "\"SpanWise Value[m]\"";
12131  myfile.width(15); myfile << "\"iSpan\"";
12132  myfile.width(30); myfile << "\"Normal Mach[-]\"";
12133  myfile.width(30); myfile << "\"Tangential Mach[-]\"";
12134  myfile.width(30); myfile << "\"3rd Component Mach[-]\"";
12135  myfile.width(30); myfile << "\"Mach Module[-]\"";
12136  myfile.width(30); myfile << "\"Normal Velocity[m/s]\"";
12137  myfile.width(30); myfile << "\"Tangential Velocity[m/s]\"";
12138  myfile.width(30); myfile << "\"3rd Component Velocity[m/s]\"";
12139  myfile.width(30); myfile << "\"Velocity Module[m/s]\"";
12140  myfile.width(30); myfile << "\"Absolute Flow Angle[deg]\"";
12141  myfile.width(30); myfile << "\"Relative Flow Angle[deg]\"";
12142  myfile << endl;
12143 
12144 
12145  for(iSpan = 0; iSpan < config[ZONE_0]->GetnSpan_iZones(val_iZone); iSpan++){
12146 
12147  myfile.width(30); myfile << SpanWiseValuesOut[iSpan];
12148  myfile.width(15); myfile << iSpan;
12149  for (iDim = 0; iDim < 4; iDim++){
12150  myfile.width(30); myfile << MachOut [val_iZone][iSpan][iDim];
12151  }
12152  for (iDim = 0; iDim < 4; iDim++){
12153  myfile.width(30); myfile << TurboVelocityOut [val_iZone][iSpan][iDim]*config[ZONE_0]->GetVelocity_Ref();
12154  }
12155  if(AbsFlowAngleOut[val_iZone][iSpan] != AbsFlowAngleOut[val_iZone][iSpan]){
12156  myfile.width(30); myfile << "0.0000";
12157  }
12158  else{
12159  myfile.width(30); myfile << AbsFlowAngleOut [val_iZone][iSpan]*180.0/PI_NUMBER;
12160  }
12161  if(FlowAngleOut[val_iZone][iSpan] != FlowAngleOut[val_iZone][iSpan]){
12162  myfile.width(30); myfile << "0.0000";
12163  }
12164  else{
12165  myfile.width(30); myfile << FlowAngleOut [val_iZone][iSpan]*180.0/PI_NUMBER;
12166  }
12167  myfile << endl;
12168  }
12169 
12170  myfile.close();
12171 
12172  }
12173 }
12174 
12175 void COutput::SpecialOutput_HarmonicBalance(CSolver *****solver, CGeometry ****geometry, CConfig **config, unsigned short iInst, unsigned short val_nInst, bool output) {
12176 
12177  /*--- Write file with flow quantities for harmonic balance HB ---*/
12178  ofstream HB_output_file;
12179  ofstream mean_HB_file;
12180 
12181  /*--- MPI Send/Recv buffers ---*/
12182  su2double *sbuf_var = NULL, *rbuf_var = NULL;
12183 
12184  /*--- Other variables ---*/
12185  unsigned short iVar, kInst;
12186  unsigned short nVar_output = 5;
12187  unsigned long current_iter = config[ZONE_0]->GetExtIter();
12188 
12189  /*--- Allocate memory for send buffer ---*/
12190  sbuf_var = new su2double[nVar_output];
12191 
12192  su2double *averages = new su2double[nVar_output];
12193  for (iVar = 0; iVar < nVar_output; iVar++)
12194  averages[iVar] = 0;
12195 
12196  /*--- Allocate memory for receive buffer ---*/
12197  if (rank == MASTER_NODE) {
12198  rbuf_var = new su2double[nVar_output];
12199 
12200  HB_output_file.precision(15);
12201  HB_output_file.open("HB_output.csv", ios::out);
12202  HB_output_file << "\"time_instance\",\"CL\",\"CD\",\"CMx\",\"CMy\",\"CMz\"" << endl;
12203 
12204  mean_HB_file.precision(15);
12205  if (current_iter == 0 && iInst == 1) {
12206  mean_HB_file.open("history_HB.plt", ios::trunc);
12207  mean_HB_file << "TITLE = \"SU2 HARMONIC BALANCE SIMULATION\"" << endl;
12208  mean_HB_file << "VARIABLES = \"Iteration\",\"CL\",\"CD\",\"CMx\",\"CMy\",\"CMz\",\"CT\",\"CQ\",\"CMerit\"" << endl;
12209  mean_HB_file << "ZONE T= \"Average Convergence History\"" << endl;
12210  }
12211  else
12212  mean_HB_file.open("history_HB.plt", ios::out | ios::app);
12213  }
12214 
12215  if (rank == MASTER_NODE) {
12216 
12217  /*--- Run through the zones, collecting the output variables
12218  N.B. Summing across processors within a given zone is being done
12219  elsewhere. ---*/
12220  for (kInst = 0; kInst < val_nInst; kInst++) {
12221 
12222  /*--- Flow solution coefficients (parallel) ---*/
12223  sbuf_var[0] = solver[ZONE_0][kInst][MESH_0][FLOW_SOL]->GetTotal_CL();
12224  sbuf_var[1] = solver[ZONE_0][kInst][INST_0][FLOW_SOL]->GetTotal_CD();
12225  sbuf_var[2] = solver[ZONE_0][kInst][INST_0][FLOW_SOL]->GetTotal_CMx();
12226  sbuf_var[3] = solver[ZONE_0][kInst][INST_0][FLOW_SOL]->GetTotal_CMy();
12227  sbuf_var[4] = solver[ZONE_0][kInst][INST_0][FLOW_SOL]->GetTotal_CMz();
12228 
12229  for (iVar = 0; iVar < nVar_output; iVar++) {
12230  rbuf_var[iVar] = sbuf_var[iVar];
12231  }
12232 
12233  HB_output_file << kInst << ", ";
12234  for (iVar = 0; iVar < nVar_output; iVar++)
12235  HB_output_file << rbuf_var[iVar] << ", ";
12236  HB_output_file << endl;
12237 
12238  /*--- Increment the total contributions from each zone, dividing by nZone as you go ---*/
12239  for (iVar = 0; iVar < nVar_output; iVar++) {
12240  averages[iVar] += (1.0/su2double(val_nInst))*rbuf_var[iVar];
12241  }
12242  }
12243  }
12244 
12245  if (rank == MASTER_NODE && iInst == INST_0) {
12246 
12247  mean_HB_file << current_iter << ", ";
12248  for (iVar = 0; iVar < nVar_output; iVar++) {
12249  mean_HB_file << averages[iVar];
12250  if (iVar < nVar_output-1)
12251  mean_HB_file << ", ";
12252  }
12253  mean_HB_file << endl;
12254  }
12255 
12256  if (rank == MASTER_NODE) {
12257  HB_output_file.close();
12258  mean_HB_file.close();
12259  delete [] rbuf_var;
12260  }
12261 
12262  delete [] sbuf_var;
12263  delete [] averages;
12264 }
12265 
12266 void COutput::SetResult_Files_Parallel(CSolver *****solver_container,
12267  CGeometry ****geometry,
12268  CConfig **config,
12269  unsigned long iExtIter,
12270  unsigned short val_nZone,
12271  unsigned short *nInst) {
12272 
12273  unsigned short iZone, iVar, iInst;
12274  unsigned long iPoint;
12275  bool compressible = true;
12276 
12277  for (iZone = 0; iZone < val_nZone; iZone++) {
12278 
12279  /*--- Bool to distinguish between the FVM and FEM solvers. ---*/
12280  unsigned short KindSolver = config[iZone]->GetKind_Solver();
12281  bool fem_solver = ((KindSolver == FEM_EULER) ||
12282  (KindSolver == FEM_NAVIER_STOKES) ||
12283  (KindSolver == FEM_RANS) ||
12284  (KindSolver == FEM_LES));
12285 
12286  /*--- Get the file output format ---*/
12287 
12288  unsigned short FileFormat = config[iZone]->GetOutput_FileFormat();
12289 
12290  for (iInst = 0; iInst < nInst[iZone]; iInst++){
12291 
12292  bool cont_adj = config[iZone]->GetContinuous_Adjoint();
12293  bool disc_adj = config[iZone]->GetDiscrete_Adjoint();
12294 
12295  /*--- Flags identifying the types of files to be written. ---*/
12296  /*--- For now, we are disabling the parallel writers for Tecplot
12297  ASCII until we have parallel versions of all file formats
12298  available. SU2_SOL will remain intact for writing files
12299  until this capability is completed. ---*/
12300 
12301  bool Wrt_Vol = config[iZone]->GetWrt_Vol_Sol();
12302  bool Wrt_Srf = config[iZone]->GetWrt_Srf_Sol();
12303  bool Wrt_Csv = config[iZone]->GetWrt_Csv_Sol();
12304 
12305 #ifdef HAVE_MPI
12306  /*--- Do not merge the connectivity or write the visualization files
12307  if we are running in parallel, unless we are using ParaView binary.
12308  Force the use of SU2_SOL to merge and write the viz. files in this
12309  case to save overhead. ---*/
12310 
12311  if ((size > SINGLE_NODE) && (FileFormat != PARAVIEW_BINARY)) {
12312  Wrt_Vol = false;
12313  Wrt_Srf = false;
12314  }
12315 #endif
12316 
12317  /*--- Check for compressible/incompressible flow problems. ---*/
12318 
12319  compressible = (config[iZone]->GetKind_Regime() == COMPRESSIBLE);
12320 
12321  /*--- First, prepare the offsets needed throughout below. ---*/
12322 
12323  PrepareOffsets(config[iZone], geometry[iZone][iInst][MESH_0]);
12324 
12325  /*--- Write out CSV files in parallel for flow and adjoint. ---*/
12326 
12327  if (rank == MASTER_NODE) cout << endl << "Writing comma-separated values (CSV) surface files." << endl;
12328 
12329  switch (config[iZone]->GetKind_Solver()) {
12330  case EULER : case NAVIER_STOKES : case RANS :
12331  if (Wrt_Csv) SetSurfaceCSV_Flow(config[iZone], geometry[iZone][iInst][MESH_0],
12332  solver_container[iZone][iInst][MESH_0][FLOW_SOL], iExtIter, iZone, iInst);
12333  break;
12334  case ADJ_EULER : case ADJ_NAVIER_STOKES : case ADJ_RANS :
12336  if (Wrt_Csv) SetSurfaceCSV_Adjoint(config[iZone], geometry[iZone][iInst][MESH_0],
12337  solver_container[iZone][iInst][MESH_0][ADJFLOW_SOL],
12338  solver_container[iZone][iInst][MESH_0][FLOW_SOL], iExtIter, iZone, iInst);
12339  break;
12340  default: break;
12341  }
12342 
12343  /*--- Write a template inlet profile file if requested. ---*/
12344 
12345  if (config[iZone]->GetWrt_InletFile()) {
12346  MergeInletCoordinates(config[iZone], geometry[iZone][iInst][MESH_0]);
12347 
12348  if (rank == MASTER_NODE) {
12349  Write_InletFile_Flow(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0]);
12350  DeallocateInletCoordinates(config[iZone], geometry[iZone][iInst][MESH_0]);
12351  }
12352  config[iZone]->SetWrt_InletFile(false);
12353  }
12354 
12355  /*--- This switch statement will become a call to a virtual function
12356  defined within each of the "physics" output child classes that loads
12357  the local data for that particular problem alone. ---*/
12358 
12359  if (rank == MASTER_NODE)
12360  cout << "Loading solution output data locally on each rank." << endl;
12361 
12362  switch (config[iZone]->GetKind_Solver()) {
12363  case EULER : case NAVIER_STOKES: case RANS :
12364  if (compressible)
12365  LoadLocalData_Flow(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone);
12366  else
12367  LoadLocalData_IncFlow(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone);
12368  break;
12369  case ADJ_EULER : case ADJ_NAVIER_STOKES : case ADJ_RANS :
12371  LoadLocalData_AdjFlow(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone);
12372  break;
12373  case FEM_ELASTICITY: case DISC_ADJ_FEM:
12374  LoadLocalData_Elasticity(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone);
12375  break;
12376  case HEAT_EQUATION_FVM:
12377  LoadLocalData_Base(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone);
12378  break;
12379  case FEM_EULER: case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES:
12380  LoadLocalData_FEM(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone);
12381  default: break;
12382  }
12383 
12384  /*--- Store the solution to be used on the final iteration with cte. lift mode. ---*/
12385 
12386  if ((!cont_adj) && (!disc_adj) && (config[iZone]->GetFixed_CL_Mode()) &&
12387  (config[iZone]->GetnExtIter()-config[iZone]->GetIter_dCL_dAlpha() -1 == iExtIter)) {
12388 
12389  if (rank == MASTER_NODE)
12390  cout << "Storing solution output data locally on each rank (cte. CL mode)." << endl;
12391 
12392  Local_Data_Copy = new su2double*[geometry[iZone][iInst][MESH_0]->GetnPoint()];
12393  for (iPoint = 0; iPoint < geometry[iZone][iInst][MESH_0]->GetnPoint(); iPoint++) {
12394  Local_Data_Copy[iPoint] = new su2double[nVar_Par];
12395  }
12396 
12397  for (iPoint = 0; iPoint < geometry[iZone][iInst][MESH_0]->GetnPoint(); iPoint++) {
12398  for (iVar = 0; iVar < nVar_Par; iVar++) {
12399  Local_Data_Copy[iPoint][iVar] = Local_Data[iPoint][iVar];
12400  }
12401  }
12402 
12403  }
12404 
12405  /*--- Recover the solution to be used on the final iteration with cte. lift mode. ---*/
12406 
12407  if ((!cont_adj) && (!disc_adj) && (config[iZone]->GetFixed_CL_Mode()) &&
12408  (config[iZone]->GetnExtIter() - 1 == iExtIter) && (Local_Data_Copy != NULL)) {
12409 
12410  if (rank == MASTER_NODE)
12411  cout << "Recovering solution output data locally on each rank (cte. CL mode)." << endl;
12412 
12413  for (iPoint = 0; iPoint < geometry[iZone][iInst][MESH_0]->GetnPoint(); iPoint++) {
12414  for (iVar = 0; iVar < nVar_Par; iVar++) {
12415  Local_Data[iPoint][iVar] = Local_Data_Copy[iPoint][iVar];
12416  }
12417  }
12418 
12419  for (iPoint = 0; iPoint < geometry[iZone][iInst][MESH_0]->GetnPoint(); iPoint++)
12420  delete [] Local_Data_Copy[iPoint];
12421  delete [] Local_Data_Copy;
12422 
12423  }
12424 
12425  /*--- After loading the data local to a processor, we perform a sorting,
12426  i.e., a linear partitioning of the data across all ranks in the communicator. ---*/
12427 
12428  if (rank == MASTER_NODE) cout << "Sorting output data across all ranks." << endl;
12429 
12430  if (fem_solver)
12431  SortOutputData_FEM(config[iZone], geometry[iZone][iInst][MESH_0]);
12432  else
12433  SortOutputData(config[iZone], geometry[iZone][iInst][MESH_0]);
12434 
12435  /*--- Write either a binary or ASCII restart file in parallel. ---*/
12436 
12437  if (config[iZone]->GetWrt_Binary_Restart()) {
12438  if (rank == MASTER_NODE) cout << "Writing binary SU2 native restart file." << endl;
12439  WriteRestart_Parallel_Binary(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone, iInst);
12440  } else {
12441  if (rank == MASTER_NODE) cout << "Writing ASCII SU2 native restart file." << endl;
12442  WriteRestart_Parallel_ASCII(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone, iInst);
12443  }
12444 
12445  /*--- Write a slice on a structured mesh if requested. ---*/
12446 
12447  if (config[iZone]->GetWrt_Slice()) {
12448  WriteCSV_Slice(config[iZone], geometry[iZone][iInst][MESH_0],
12449  solver_container[iZone][iInst][MESH_0][FLOW_SOL], iExtIter, iZone, 0);
12450  WriteCSV_Slice(config[iZone], geometry[iZone][iInst][MESH_0],
12451  solver_container[iZone][iInst][MESH_0][FLOW_SOL], iExtIter, iZone, 1);
12452  }
12453 
12454  /*--- Write the solution files if they are requested and we are executing
12455  with a single rank (all data on one proc and no comm. overhead). Once we
12456  have parallel binary versions of Tecplot / ParaView / CGNS / etc., we
12457  can allow the write of the viz. files as well. ---*/
12458 
12459  if ((Wrt_Vol || Wrt_Srf) && !fem_solver) {
12460 
12461  /*--- First, sort all connectivity into linearly partitioned chunks of elements. ---*/
12462 
12463  if (rank == MASTER_NODE)
12464  cout << "Preparing element connectivity across all ranks." << endl;
12465 
12466  if (fem_solver)
12467  SortConnectivity_FEM(config[iZone], geometry[iZone][iInst][MESH_0], iZone);
12468  else
12469  SortConnectivity(config[iZone], geometry[iZone][iInst][MESH_0], iZone);
12470 
12471  /*--- Sort the surface data and renumber if for writing. ---*/
12472 
12473  if (fem_solver)
12474  SortOutputData_Surface_FEM(config[iZone], geometry[iZone][iInst][MESH_0]);
12475  else
12476  SortOutputData_Surface(config[iZone], geometry[iZone][iInst][MESH_0]);
12477 
12478  /*--- Write Tecplot/ParaView ASCII files for the volume and/or surface solutions. ---*/
12479 
12480  if (Wrt_Vol) {
12481 
12482  switch (FileFormat) {
12483 
12484  case TECPLOT:
12485 
12486  /*--- Write a Tecplot ASCII file ---*/
12487 
12488  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file volume solution file." << endl;
12489  WriteTecplotASCII_Parallel(config[iZone], geometry[iZone][iInst][MESH_0],
12490  solver_container[iZone][iInst][MESH_0], iZone, val_nZone, iInst, nInst[iZone], false);
12491  break;
12492 
12493  case FIELDVIEW:
12494 
12495  /*--- We do not yet have a version of FieldView ASCII for new parallel output. ---*/
12496 
12497  if (rank == MASTER_NODE) cout << "FieldView ASCII volume files not available in serial with SU2_CFD." << endl;
12498  if (rank == MASTER_NODE) cout << " Run SU2_SOL to generate FieldView ASCII." << endl;
12499 
12500  break;
12501 
12502  case TECPLOT_BINARY:
12503 
12504  /*--- Write a Tecplot ASCII file instead for now in serial. ---*/
12505 
12506  if (rank == MASTER_NODE) cout << "Tecplot binary volume files not available in serial with SU2_CFD." << endl;
12507  if (rank == MASTER_NODE) cout << " Run SU2_SOL to generate Tecplot binary." << endl;
12508  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file volume solution file instead." << endl;
12509  WriteTecplotASCII_Parallel(config[iZone], geometry[iZone][iInst][MESH_0],
12510  solver_container[iZone][iInst][MESH_0], iZone, val_nZone, iInst, nInst[iZone], false);
12511  break;
12512 
12513  case FIELDVIEW_BINARY:
12514 
12515  /*--- FieldView binary files not yet available for parallel output. ---*/
12516 
12517  if (rank == MASTER_NODE) cout << "FieldView ASCII volume files not available in serial with SU2_CFD." << endl;
12518  if (rank == MASTER_NODE) cout << " Run SU2_SOL to generate FieldView ASCII." << endl;
12519  break;
12520 
12521  case PARAVIEW:
12522 
12523  /*--- Write a Paraview ASCII file ---*/
12524 
12525  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII volume solution file." << endl;
12526  WriteParaViewASCII_Parallel(config[iZone], geometry[iZone][iInst][MESH_0],
12527  solver_container[iZone][iInst][MESH_0], iZone, val_nZone, iInst, nInst[iZone], false);
12528  break;
12529 
12530  case PARAVIEW_BINARY:
12531 
12532  /*--- Write a Paraview binary file ---*/
12533 
12534  if (rank == MASTER_NODE) cout << "Writing Paraview binary volume solution file." << endl;
12535  WriteParaViewBinary_Parallel(config[iZone], geometry[iZone][iInst][MESH_0],
12536  solver_container[iZone][iInst][MESH_0], iZone, val_nZone, false);
12537  break;
12538 
12539  default:
12540  break;
12541  }
12542 
12543  }
12544 
12545  if (Wrt_Srf) {
12546 
12547  switch (FileFormat) {
12548 
12549  case TECPLOT:
12550 
12551  /*--- Write a Tecplot ASCII file ---*/
12552 
12553  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file surface solution file." << endl;
12554  WriteTecplotASCII_Parallel(config[iZone], geometry[iZone][iInst][MESH_0],
12555  solver_container[iZone][iInst][MESH_0], iZone, val_nZone, iInst, nInst[iZone], true);
12556  break;
12557 
12558  case TECPLOT_BINARY:
12559 
12560  /*--- Write a Tecplot ASCII file instead for now in serial. ---*/
12561 
12562  if (rank == MASTER_NODE) cout << "Tecplot binary surface files not available in serial with SU2_CFD." << endl;
12563  if (rank == MASTER_NODE) cout << " Run SU2_SOL to generate Tecplot binary." << endl;
12564  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file surface solution file instead." << endl;
12565  WriteTecplotASCII_Parallel(config[iZone], geometry[iZone][iInst][MESH_0],
12566  solver_container[iZone][iInst][MESH_0], iZone, val_nZone, iInst, nInst[iZone], true);
12567  break;
12568 
12569  case PARAVIEW:
12570 
12571  /*--- Write a Paraview ASCII file ---*/
12572 
12573  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII surface solution file." << endl;
12574  WriteParaViewASCII_Parallel(config[iZone], geometry[iZone][iInst][MESH_0],
12575  solver_container[iZone][iInst][MESH_0], iZone, val_nZone, iInst, nInst[iZone], true);
12576  break;
12577 
12578  case PARAVIEW_BINARY:
12579 
12580  /*--- Write a Paraview binary file ---*/
12581 
12582  if (rank == MASTER_NODE) cout << "Writing Paraview binary surface solution file." << endl;
12583  WriteParaViewBinary_Parallel(config[iZone], geometry[iZone][iInst][MESH_0],
12584  solver_container[iZone][iInst][MESH_0], iZone, val_nZone, true);
12585  break;
12586 
12587 
12588  default:
12589  break;
12590  }
12591 
12592  }
12593 
12594  /*--- Clean up the connectivity data that was allocated for output. ---*/
12595 
12596  DeallocateConnectivity_Parallel(config[iZone], geometry[iZone][iInst][MESH_0], false);
12597  DeallocateConnectivity_Parallel(config[iZone], geometry[iZone][iInst][MESH_0], true);
12598 
12599  /*--- Clean up the surface data that was only needed for output. ---*/
12600 
12601  DeallocateSurfaceData_Parallel(config[iZone], geometry[iZone][iInst][MESH_0]);
12602 
12603  }
12604 
12605  /*--- Deallocate the nodal data needed for writing restarts. ---*/
12606 
12607  DeallocateData_Parallel(config[iZone], geometry[iZone][iInst][MESH_0]);
12608 
12609  /*--- Clear the variable names list. ---*/
12610 
12611  Variable_Names.clear();
12612 
12613  }
12614  }
12615 }
12616 
12617 void COutput::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
12618 
12619  unsigned short iDim;
12620  unsigned short Kind_Solver = config->GetKind_Solver();
12621  unsigned short nDim = geometry->GetnDim();
12622 
12623  unsigned long iVar, jVar;
12624  unsigned long iPoint, jPoint, FirstIndex = NONE, SecondIndex = NONE, iMarker, iVertex;
12625  unsigned long nVar_First = 0, nVar_Second = 0, nVar_Consv_Par = 0;
12626 
12627  su2double RefArea = config->GetRefArea();
12628  su2double Gamma = config->GetGamma();
12629  su2double RefVel2;
12630  su2double Gas_Constant, Mach2Vel, Mach_Motion, RefDensity, RefPressure = 0.0, factor = 0.0;
12631  su2double *Aux_Frict_x = NULL, *Aux_Frict_y = NULL, *Aux_Frict_z = NULL, *Aux_Heat = NULL, *Aux_yPlus = NULL, *Aux_Buffet = NULL;
12632  su2double *Grid_Vel = NULL;
12633 
12634  bool transition = (config->GetKind_Trans_Model() == BC);
12635  bool grid_movement = (config->GetGrid_Movement());
12636  bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
12637 
12638  int *Local_Halo = NULL;
12639 
12640  stringstream varname;
12641 
12642  /*--- Set the non-dimensionalization for coefficients. ---*/
12643 
12644  if (grid_movement) {
12645  Gas_Constant = config->GetGas_ConstantND();
12646  Mach2Vel = sqrt(Gamma*Gas_Constant*config->GetTemperature_FreeStreamND());
12647  Mach_Motion = config->GetMach_Motion();
12648  RefVel2 = (Mach_Motion*Mach2Vel)*(Mach_Motion*Mach2Vel);
12649  }
12650  else {
12651  RefVel2 = 0.0;
12652  for (iDim = 0; iDim < nDim; iDim++)
12653  RefVel2 += solver[FLOW_SOL]->GetVelocity_Inf(iDim)*solver[FLOW_SOL]->GetVelocity_Inf(iDim);
12654  }
12655  RefDensity = solver[FLOW_SOL]->GetDensity_Inf();
12656  RefPressure = solver[FLOW_SOL]->GetPressure_Inf();
12657  factor = 1.0 / (0.5*RefDensity*RefArea*RefVel2);
12658 
12659  /*--- Use a switch statement to decide how many solver containers we have
12660  in this zone for output. ---*/
12661 
12662  switch (config->GetKind_Solver()) {
12663  case EULER : case NAVIER_STOKES: FirstIndex = FLOW_SOL; SecondIndex = NONE; break;
12664  case RANS : FirstIndex = FLOW_SOL; SecondIndex = TURB_SOL; break;
12665  default: SecondIndex = NONE; break;
12666  }
12667 
12668  nVar_First = solver[FirstIndex]->GetnVar();
12669  if (SecondIndex != NONE) nVar_Second = solver[SecondIndex]->GetnVar();
12670  nVar_Consv_Par = nVar_First + nVar_Second;
12671 
12672  /*--------------------------------------------------------------------------*/
12673  /*--- Step 1: Register the variables that will be output. To register a ---*/
12674  /*--- variable, two things are required. First, increment the ---*/
12675  /*--- counter for the number of variables (nVar_Par), which ---*/
12676  /*--- controls the size of the data structure allocation, i.e., ---*/
12677  /*--- the number of columns in an nPoint x nVar structure. ---*/
12678  /*--- Second, add a name for the variable to the vector that ---*/
12679  /*--- holds the string names. ---*/
12680  /*--------------------------------------------------------------------------*/
12681 
12682  /*--- All output files first need the grid coordinates. ---*/
12683 
12684  nVar_Par = 1; Variable_Names.push_back("x");
12685  nVar_Par += 1; Variable_Names.push_back("y");
12686  if (geometry->GetnDim() == 3) {
12687  nVar_Par += 1; Variable_Names.push_back("z");
12688  }
12689 
12690  /*--- At a mininum, the restarts and visualization files need the
12691  conservative variables, so these follow next. ---*/
12692 
12693  nVar_Par += nVar_Consv_Par;
12694 
12695  Variable_Names.push_back("Density");
12696  Variable_Names.push_back("Momentum_x");
12697  Variable_Names.push_back("Momentum_y");
12698  if (geometry->GetnDim() == 3) Variable_Names.push_back("Momentum_z");
12699  Variable_Names.push_back("Energy");
12700 
12701  if (SecondIndex != NONE) {
12702  if (config->GetKind_Turb_Model() == SST) {
12703  Variable_Names.push_back("TKE");
12704  Variable_Names.push_back("Omega");
12705  } else {
12706  /*--- S-A variants ---*/
12707  Variable_Names.push_back("Nu_Tilde");
12708  }
12709  }
12710 
12711  /*--- If requested, register the limiter and residuals for all of the
12712  equations in the current flow problem. ---*/
12713 
12714  if (!config->GetLow_MemoryOutput()) {
12715 
12716  /*--- Add the limiters ---*/
12717 
12718  if (config->GetWrt_Limiters()) {
12719  nVar_Par += nVar_Consv_Par;
12720 
12721  Variable_Names.push_back("Limiter_Density");
12722  Variable_Names.push_back("Limiter_Momentum_x");
12723  Variable_Names.push_back("Limiter_Momentum_y");
12724  if (geometry->GetnDim() == 3) Variable_Names.push_back("Limiter_Momentum_z");
12725  Variable_Names.push_back("Limiter_Energy");
12726 
12727  if (SecondIndex != NONE) {
12728  if (config->GetKind_Turb_Model() == SST) {
12729  Variable_Names.push_back("Limiter_TKE");
12730  Variable_Names.push_back("Limiter_Omega");
12731  } else {
12732  /*--- S-A variants ---*/
12733  Variable_Names.push_back("Limiter_Nu_Tilde");
12734  }
12735  }
12736  }
12737 
12738  /*--- Add the residuals ---*/
12739 
12740  if (config->GetWrt_Residuals()) {
12741  nVar_Par += nVar_Consv_Par;
12742 
12743  Variable_Names.push_back("Residual_Density");
12744  Variable_Names.push_back("Residual_Momentum_x");
12745  Variable_Names.push_back("Residual_Momentum_y");
12746  if (geometry->GetnDim() == 3) Variable_Names.push_back("Residual_Momentum_z");
12747  Variable_Names.push_back("Residual_Energy");
12748 
12749  if (SecondIndex != NONE) {
12750  if (config->GetKind_Turb_Model() == SST) {
12751  Variable_Names.push_back("Residual_TKE");
12752  Variable_Names.push_back("Residual_Omega");
12753  } else {
12754  /*--- S-A variants ---*/
12755  Variable_Names.push_back("Residual_Nu_Tilde");
12756  }
12757  }
12758  }
12759 
12760  /*--- Add the grid velocity. ---*/
12761 
12762  if (grid_movement) {
12763  if (geometry->GetnDim() == 2) nVar_Par += 2;
12764  else if (geometry->GetnDim() == 3) nVar_Par += 3;
12765 
12766  Variable_Names.push_back("Grid_Velocity_x");
12767  Variable_Names.push_back("Grid_Velocity_y");
12768  if (geometry->GetnDim() == 3) Variable_Names.push_back("Grid_Velocity_z");
12769  }
12770 
12771 
12772  /*--- Add Pressure, Temperature, Cp, Mach. ---*/
12773 
12774  nVar_Par += 1;
12775  Variable_Names.push_back("Pressure");
12776 
12777  nVar_Par += 2;
12778  Variable_Names.push_back("Temperature");
12779  Variable_Names.push_back("Mach");
12780 
12781  nVar_Par += 1;
12782  if ((config->GetOutput_FileFormat() == PARAVIEW) ||
12783  (config->GetOutput_FileFormat() == PARAVIEW_BINARY)){
12784  Variable_Names.push_back("Pressure_Coefficient");
12785  } else {
12786  Variable_Names.push_back("C<sub>p</sub>");
12787  }
12788 
12789  /*--- Add Laminar Viscosity, Skin Friction, Heat Flux, & yPlus to the restart file ---*/
12790 
12791  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
12792  if ((config->GetOutput_FileFormat() == PARAVIEW) ||
12793  (config->GetOutput_FileFormat() == PARAVIEW_BINARY)){
12794  nVar_Par += 1; Variable_Names.push_back("Laminar_Viscosity");
12795  nVar_Par += 2;
12796  Variable_Names.push_back("Skin_Friction_Coefficient_x");
12797  Variable_Names.push_back("Skin_Friction_Coefficient_y");
12798  if (geometry->GetnDim() == 3) {
12799  nVar_Par += 1; Variable_Names.push_back("Skin_Friction_Coefficient_z");
12800  }
12801  nVar_Par += 1;
12802  Variable_Names.push_back("Heat_Flux");
12803  } else {
12804  nVar_Par += 1; Variable_Names.push_back("<greek>m</greek>");
12805  nVar_Par += 2;
12806  Variable_Names.push_back("C<sub>f</sub>_x");
12807  Variable_Names.push_back("C<sub>f</sub>_y");
12808  if (geometry->GetnDim() == 3) {
12809  nVar_Par += 1; Variable_Names.push_back("C<sub>f</sub>_z");
12810  }
12811  if (config->GetBuffet_Monitoring() || config->GetKind_ObjFunc() == BUFFET_SENSOR){
12812  Variable_Names.push_back("Buffet_Sensor");
12813  nVar_Par += 1;
12814  }
12815  nVar_Par += 1;
12816  Variable_Names.push_back("h");
12817  }
12818  }
12819 
12820  /*--- Add Eddy Viscosity. ---*/
12821 
12822  if (Kind_Solver == RANS) {
12823  nVar_Par += 2;
12824  if ((config->GetOutput_FileFormat() == PARAVIEW) ||
12825  (config->GetOutput_FileFormat() == PARAVIEW_BINARY)){
12826  Variable_Names.push_back("Y_Plus");
12827  Variable_Names.push_back("Eddy_Viscosity");
12828  } else {
12829  Variable_Names.push_back("y<sup>+</sup>");
12830  Variable_Names.push_back("<greek>m</greek><sub>t</sub>");
12831  }
12832  }
12833 
12834  /*--- Add the distance to the nearest sharp edge if requested. ---*/
12835 
12836  if (config->GetWrt_SharpEdges()) {
12837  nVar_Par += 1;
12838  Variable_Names.push_back("Sharp_Edge_Dist");
12839  }
12840 
12841  /*--- Add the intermittency for the BC trans. model. ---*/
12842 
12843  if (transition) {
12844  nVar_Par += 1;
12845  if ((config->GetOutput_FileFormat() == PARAVIEW) ||
12846  (config->GetOutput_FileFormat() == PARAVIEW_BINARY)){
12847  Variable_Names.push_back("gamma_BC");
12848  } else {
12849  Variable_Names.push_back("<greek>g</greek><sub>BC</sub>");
12850  }
12851  }
12852 
12853  if (config->GetKind_HybridRANSLES()!=NO_HYBRIDRANSLES){
12854  nVar_Par +=1;
12855  Variable_Names.push_back("DES_LengthScale");
12856  nVar_Par +=1;
12857  Variable_Names.push_back("Wall_Distance");
12858  }
12859 
12860  if (config->GetKind_RoeLowDiss() != NO_ROELOWDISS){
12861  nVar_Par +=1;
12862  Variable_Names.push_back("Roe_Dissipation");
12863  }
12864 
12865  /*--- New variables get registered here before the end of the loop. ---*/
12866 
12867  }
12868 
12869  /*--- Auxiliary vectors for variables defined on surfaces only. ---*/
12870 
12871  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
12872  Aux_Frict_x = new su2double[geometry->GetnPoint()];
12873  Aux_Frict_y = new su2double[geometry->GetnPoint()];
12874  Aux_Frict_z = new su2double[geometry->GetnPoint()];
12875  Aux_Heat = new su2double[geometry->GetnPoint()];
12876  Aux_yPlus = new su2double[geometry->GetnPoint()];
12877  Aux_Buffet = new su2double[geometry->GetnPoint()];
12878 
12879  /*--- First, loop through the mesh in order to find and store the
12880  value of the viscous coefficients at any surface nodes. They
12881  will be placed in an auxiliary vector and then communicated like
12882  all other volumetric variables. ---*/
12883 
12884  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
12885  Aux_Frict_x[iPoint] = 0.0;
12886  Aux_Frict_y[iPoint] = 0.0;
12887  Aux_Frict_z[iPoint] = 0.0;
12888  Aux_Heat[iPoint] = 0.0;
12889  Aux_yPlus[iPoint] = 0.0;
12890  Aux_Buffet[iPoint] = 0.0;
12891  }
12892  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
12893  if (config->GetMarker_All_Plotting(iMarker) == YES) {
12894  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
12895  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
12896  Aux_Frict_x[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 0);
12897  Aux_Frict_y[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 1);
12898  if (geometry->GetnDim() == 3) Aux_Frict_z[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 2);
12899  Aux_Heat[iPoint] = solver[FLOW_SOL]->GetHeatFlux(iMarker, iVertex);
12900  Aux_yPlus[iPoint] = solver[FLOW_SOL]->GetYPlus(iMarker, iVertex);
12901  if (config->GetBuffet_Monitoring() || config->GetKind_ObjFunc() == BUFFET_SENSOR) Aux_Buffet[iPoint] = solver[FLOW_SOL]->GetBuffetSensor(iMarker, iVertex);
12902  }
12903  }
12904  }
12905  }
12906 
12907  /*--- Allocate the local data structure now that we know how many
12908  variables are in the output. ---*/
12909 
12910  Local_Data = new su2double*[geometry->GetnPoint()];
12911  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
12912  Local_Data[iPoint] = new su2double[nVar_Par];
12913  }
12914 
12915  Local_Halo = new int[geometry->GetnPoint()];
12916  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
12917  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
12918 
12919  /*--- Search all send/recv boundaries on this partition for any periodic
12920  nodes that were part of the original domain. We want to recover these
12921  for visualization purposes. ---*/
12922 
12923  if (!Wrt_Halo) {
12924  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
12925  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
12926 
12927  /*--- Checking for less than or equal to the rank, because there may
12928  be some periodic halo nodes that send info to the same rank. ---*/
12929 
12930  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
12931  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
12932  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
12933  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
12934  if (isPeriodic) Local_Halo[iPoint] = false;
12935  }
12936  }
12937  }
12938  }
12939 
12940  /*--------------------------------------------------------------------------*/
12941  /*--- Step 2: Loop over all grid nodes and load up the desired data for ---*/
12942  /*--- the restart and vizualization files. Note that we need to ---*/
12943  /*--- increment the iVar variable after each variable load. ---*/
12944  /*--- The idea is that we're filling up the columns of field ---*/
12945  /*--- data for each iPoint (row) of the data structure. ---*/
12946  /*--- This data will then be sorted, communicated, and written ---*/
12947  /*--- to files automatically after this routine. Note that the ---*/
12948  /*--- ordering of the data loading MUST match the order of the ---*/
12949  /*--- variable registration above for the files to be correct. ---*/
12950  /*--------------------------------------------------------------------------*/
12951 
12952  jPoint = 0;
12953 
12954  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
12955 
12956  /*--- Check for halos & write only if requested ---*/
12957 
12958  if (!Local_Halo[iPoint] || Wrt_Halo) {
12959 
12960  /*--- Restart the column index with each new point. ---*/
12961 
12962  iVar = 0;
12963 
12964  /*--- Load the grid node coordinate values. ---*/
12965 
12966  for (iDim = 0; iDim < geometry->GetnDim(); iDim++) {
12967  Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetCoord(iDim);
12968  if (config->GetSystemMeasurements() == US)
12969  Local_Data[jPoint][iVar] *= 12.0;
12970  iVar++;
12971  }
12972 
12973  /*--- Load the conservative variable states for the mean flow variables. ---*/
12974 
12975  for (jVar = 0; jVar < nVar_First; jVar++) {
12976  Local_Data[jPoint][iVar] = solver[FirstIndex]->node[iPoint]->GetSolution(jVar);
12977  iVar++;
12978  }
12979 
12980  /*--- If this is RANS, i.e., the second solver container is not empty,
12981  then load data for the conservative turbulence variables. ---*/
12982 
12983  if (SecondIndex != NONE) {
12984  for (jVar = 0; jVar < nVar_Second; jVar++) {
12985  Local_Data[jPoint][iVar] = solver[SecondIndex]->node[iPoint]->GetSolution(jVar);
12986  iVar++;
12987  }
12988  }
12989 
12990  /*--- If limiters and/or residuals are requested. ---*/
12991  if (!config->GetLow_MemoryOutput()) {
12992 
12993  /*--- Limiters ---*/
12994  if (config->GetWrt_Limiters()) {
12995  /*--- Mean Flow Limiters ---*/
12996  for (jVar = 0; jVar < nVar_First; jVar++) {
12997  Local_Data[jPoint][iVar] = solver[FirstIndex]->node[iPoint]->GetLimiter_Primitive(jVar);
12998  iVar++;
12999  }
13000  /*--- RANS Limiters ---*/
13001  if (SecondIndex != NONE) {
13002  for (jVar = 0; jVar < nVar_Second; jVar++) {
13003  Local_Data[jPoint][iVar] = solver[SecondIndex]->node[iPoint]->GetLimiter_Primitive(jVar);
13004  iVar++;
13005  }
13006  }
13007  }
13008 
13009  /*--- Residuals ---*/
13010  if (config->GetWrt_Residuals()) {
13011  /*--- Mean Flow Residuals ---*/
13012  for (jVar = 0; jVar < nVar_First; jVar++) {
13013  Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes.GetBlock(iPoint, jVar);
13014  iVar++;
13015  }
13016  /*--- RANS Residuals ---*/
13017  if (SecondIndex != NONE) {
13018  for (jVar = 0; jVar < nVar_Second; jVar++) {
13019  Local_Data[jPoint][iVar] = solver[SecondIndex]->LinSysRes.GetBlock(iPoint, jVar);
13020  iVar++;
13021  }
13022  }
13023  }
13024  }
13025 
13026  if (!config->GetLow_MemoryOutput()) {
13027 
13028  /*--- Load buffers with the three grid velocity components. ---*/
13029 
13030  if (grid_movement) {
13031  Grid_Vel = geometry->node[iPoint]->GetGridVel();
13032  Local_Data[jPoint][iVar] = Grid_Vel[0]; iVar++;
13033  Local_Data[jPoint][iVar] = Grid_Vel[1]; iVar++;
13034  if (geometry->GetnDim() == 3) {
13035  Local_Data[jPoint][iVar] = Grid_Vel[2];
13036  iVar++;
13037  }
13038  }
13039 
13040  /*--- Load data for the pressure, temperature, Cp, and Mach variables. ---*/
13041 
13042  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->node[iPoint]->GetPressure(); iVar++;
13043  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->node[iPoint]->GetTemperature(); iVar++;
13044  Local_Data[jPoint][iVar] = sqrt(solver[FLOW_SOL]->node[iPoint]->GetVelocity2())/solver[FLOW_SOL]->node[iPoint]->GetSoundSpeed(); iVar++;
13045  Local_Data[jPoint][iVar] = (solver[FLOW_SOL]->node[iPoint]->GetPressure() - RefPressure)*factor*RefArea; iVar++;
13046 
13047  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
13048 
13049  /*--- Load data for the laminar viscosity. ---*/
13050 
13051  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->node[iPoint]->GetLaminarViscosity(); iVar++;
13052 
13053  /*--- Load data for the skin friction, heat flux, buffet, and y-plus. ---*/
13054 
13055  Local_Data[jPoint][iVar] = Aux_Frict_x[iPoint]; iVar++;
13056  Local_Data[jPoint][iVar] = Aux_Frict_y[iPoint]; iVar++;
13057  if (geometry->GetnDim() == 3) {
13058  Local_Data[jPoint][iVar] = Aux_Frict_z[iPoint];
13059  iVar++;
13060  }
13061  if (config->GetBuffet_Monitoring() || config->GetKind_ObjFunc() == BUFFET_SENSOR) {
13062  Local_Data[jPoint][iVar] = Aux_Buffet[iPoint];
13063  iVar++;
13064  }
13065  Local_Data[jPoint][iVar] = Aux_Heat[iPoint]; iVar++;
13066 
13067  }
13068 
13069  /*--- Load data for the Eddy viscosity for RANS. ---*/
13070 
13071  if (Kind_Solver == RANS) {
13072  Local_Data[jPoint][iVar] = Aux_yPlus[iPoint]; iVar++;
13073  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->node[iPoint]->GetEddyViscosity(); iVar++;
13074  }
13075 
13076  /*--- Load data for the distance to the nearest sharp edge. ---*/
13077 
13078  if (config->GetWrt_SharpEdges()) {
13079  Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetSharpEdge_Distance(); iVar++;
13080  }
13081 
13082  /*--- Load data for the intermittency of the BC trans. model. ---*/
13083 
13084  if (transition) {
13085  Local_Data[jPoint][iVar] = solver[TURB_SOL]->node[iPoint]->GetGammaBC(); iVar++;
13086  }
13087 
13088  if (config->GetKind_HybridRANSLES()!=NO_HYBRIDRANSLES){
13089  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->node[iPoint]->GetDES_LengthScale(); iVar++;
13090  Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetWall_Distance(); iVar++;
13091  }
13092 
13093  if (config->GetKind_RoeLowDiss() != NO_ROELOWDISS){
13094  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->node[iPoint]->GetRoe_Dissipation(); iVar++;
13095  }
13096 
13097  /*--- New variables can be loaded to the Local_Data structure here,
13098  assuming they were registered above correctly. ---*/
13099 
13100  }
13101 
13102  /*--- Increment the point counter, as there may have been halos we
13103  skipped over during the data loading. ---*/
13104 
13105  jPoint++;
13106 
13107  }
13108  }
13109 
13110  /*--- Free memory for auxiliary vectors. ---*/
13111 
13112  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
13113  delete [] Aux_Frict_x;
13114  delete [] Aux_Frict_y;
13115  delete [] Aux_Frict_z;
13116  delete [] Aux_Heat;
13117  delete [] Aux_yPlus;
13118  delete [] Aux_Buffet;
13119  }
13120 
13121  delete [] Local_Halo;
13122 
13123 }
13124 
13125 void COutput::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
13126 
13127  unsigned short iDim;
13128  unsigned short Kind_Solver = config->GetKind_Solver();
13129  unsigned short nDim = geometry->GetnDim();
13130 
13131  unsigned long iVar, jVar;
13132  unsigned long iPoint, jPoint, FirstIndex = NONE, SecondIndex = NONE, iMarker, iVertex;
13133  unsigned long nVar_First = 0, nVar_Second = 0, nVar_Consv_Par = 0;
13134 
13135  su2double RefArea = config->GetRefArea();
13136  su2double RefVel2 = 0.0;
13137  su2double factor = 0.0;
13138  su2double RefDensity = 0.0, RefPressure = 0.0;
13139  su2double *Aux_Frict_x = NULL, *Aux_Frict_y = NULL, *Aux_Frict_z = NULL, *Aux_Heat = NULL, *Aux_yPlus = NULL;
13140  su2double *Grid_Vel = NULL;
13141 
13142  bool transition = (config->GetKind_Trans_Model() == BC);
13143  bool grid_movement = (config->GetGrid_Movement());
13144  bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
13145  bool variable_density = (config->GetKind_DensityModel() == VARIABLE);
13146  bool energy = config->GetEnergy_Equation();
13147  bool weakly_coupled_heat = config->GetWeakly_Coupled_Heat();
13148 
13149  int *Local_Halo = NULL;
13150 
13151  stringstream varname;
13152 
13153  /*--- Evaluate reference values for non-dimensionalization.
13154  For dimensional or non-dim based on initial values, use
13155  the far-field state (inf). For a custom non-dim based
13156  on user-provided reference values, use the ref values
13157  to compute the forces. ---*/
13158 
13159  if ((config->GetRef_Inc_NonDim() == DIMENSIONAL) ||
13160  (config->GetRef_Inc_NonDim() == INITIAL_VALUES)) {
13161  RefDensity = solver[FLOW_SOL]->GetDensity_Inf();
13162  RefVel2 = 0.0;
13163  for (iDim = 0; iDim < nDim; iDim++)
13164  RefVel2 += solver[FLOW_SOL]->GetVelocity_Inf(iDim)*solver[FLOW_SOL]->GetVelocity_Inf(iDim);
13165  }
13166  else if (config->GetRef_Inc_NonDim() == REFERENCE_VALUES) {
13167  RefDensity = config->GetInc_Density_Ref();
13168  RefVel2 = config->GetInc_Velocity_Ref()*config->GetInc_Velocity_Ref();
13169  }
13170 
13171  /*--- Reference pressure is always the far-field value (0.0). ---*/
13172 
13173  RefPressure = solver[FLOW_SOL]->GetPressure_Inf();
13174 
13175  /*--- Compute factor for force coefficients. ---*/
13176 
13177  factor = 1.0 / (0.5*RefDensity*RefArea*RefVel2);
13178 
13179  /*--- Use a switch statement to decide how many solver containers we have
13180  in this zone for output. ---*/
13181 
13182  switch (config->GetKind_Solver()) {
13183  case EULER : case NAVIER_STOKES: FirstIndex = FLOW_SOL; SecondIndex = NONE; break;
13184  case RANS : FirstIndex = FLOW_SOL; SecondIndex = TURB_SOL; break;
13185  default: SecondIndex = NONE; break;
13186  }
13187 
13188  nVar_First = solver[FirstIndex]->GetnVar();
13189  if ((!energy) && (!weakly_coupled_heat)) nVar_First--;
13190  if (SecondIndex != NONE) nVar_Second = solver[SecondIndex]->GetnVar();
13191  nVar_Consv_Par = nVar_First + nVar_Second;
13192 
13193  /*--------------------------------------------------------------------------*/
13194  /*--- Step 1: Register the variables that will be output. To register a ---*/
13195  /*--- variable, two things are required. First, increment the ---*/
13196  /*--- counter for the number of variables (nVar_Par), which ---*/
13197  /*--- controls the size of the data structure allocation, i.e., ---*/
13198  /*--- the number of columns in an nPoint x nVar structure. ---*/
13199  /*--- Second, add a name for the variable to the vector that ---*/
13200  /*--- holds the string names. ---*/
13201  /*--------------------------------------------------------------------------*/
13202 
13203  /*--- All output files first need the grid coordinates. ---*/
13204 
13205  nVar_Par = 1; Variable_Names.push_back("x");
13206  nVar_Par += 1; Variable_Names.push_back("y");
13207  if (geometry->GetnDim() == 3) {
13208  nVar_Par += 1; Variable_Names.push_back("z");
13209  }
13210 
13211  /*--- At a mininum, the restarts and visualization files need the
13212  conservative variables, so these follow next. ---*/
13213 
13214  nVar_Par += nVar_Consv_Par;
13215 
13216  /*--- The incompressible solver uses primitives as the working variables. ---*/
13217 
13218  Variable_Names.push_back("Pressure");
13219  Variable_Names.push_back("Velocity_x");
13220  Variable_Names.push_back("Velocity_y");
13221  if (geometry->GetnDim() == 3) Variable_Names.push_back("Velocity_z");
13222  if (energy || weakly_coupled_heat) Variable_Names.push_back("Temperature");
13223 
13224  if (SecondIndex != NONE) {
13225  if (config->GetKind_Turb_Model() == SST) {
13226  Variable_Names.push_back("TKE");
13227  Variable_Names.push_back("Omega");
13228  } else {
13229  /*--- S-A variants ---*/
13230  Variable_Names.push_back("Nu_Tilde");
13231  }
13232  }
13233 
13234  /*--- If requested, register the limiter and residuals for all of the
13235  equations in the current flow problem. ---*/
13236 
13237  if (!config->GetLow_MemoryOutput()) {
13238 
13239  /*--- Add the limiters ---*/
13240 
13241  if (config->GetWrt_Limiters()) {
13242  nVar_Par += nVar_Consv_Par;
13243 
13244  Variable_Names.push_back("Limiter_Pressure");
13245  Variable_Names.push_back("Limiter_Velocity_x");
13246  Variable_Names.push_back("Limiter_Velocity_y");
13247  if (geometry->GetnDim() == 3) Variable_Names.push_back("Limiter_Velocity_z");
13248  if (energy || weakly_coupled_heat)
13249  Variable_Names.push_back("Limiter_Temperature");
13250 
13251  if (SecondIndex != NONE) {
13252  if (config->GetKind_Turb_Model() == SST) {
13253  Variable_Names.push_back("Limiter_TKE");
13254  Variable_Names.push_back("Limiter_Omega");
13255  } else {
13256  /*--- S-A variants ---*/
13257  Variable_Names.push_back("Limiter_Nu_Tilde");
13258  }
13259  }
13260  }
13261 
13262  /*--- Add the residuals ---*/
13263 
13264  if (config->GetWrt_Residuals()) {
13265  nVar_Par += nVar_Consv_Par;
13266 
13267  Variable_Names.push_back("Residual_Pressure");
13268  Variable_Names.push_back("Residual_Velocity_x");
13269  Variable_Names.push_back("Residual_Velocity_y");
13270  if (geometry->GetnDim() == 3) Variable_Names.push_back("Residual_Velocity_z");
13271  if (energy || weakly_coupled_heat)
13272  Variable_Names.push_back("Residual_Temperature");
13273 
13274  if (SecondIndex != NONE) {
13275  if (config->GetKind_Turb_Model() == SST) {
13276  Variable_Names.push_back("Residual_TKE");
13277  Variable_Names.push_back("Residual_Omega");
13278  } else {
13279  /*--- S-A variants ---*/
13280  Variable_Names.push_back("Residual_Nu_Tilde");
13281  }
13282  }
13283  }
13284 
13285  /*--- Add the grid velocity. ---*/
13286 
13287  if (grid_movement) {
13288  if (geometry->GetnDim() == 2) nVar_Par += 2;
13289  else if (geometry->GetnDim() == 3) nVar_Par += 3;
13290 
13291  Variable_Names.push_back("Grid_Velocity_x");
13292  Variable_Names.push_back("Grid_Velocity_y");
13293  if (geometry->GetnDim() == 3) Variable_Names.push_back("Grid_Velocity_z");
13294  }
13295 
13296  /*--- Add Cp. ---*/
13297 
13298  nVar_Par += 1;
13299  if ((config->GetOutput_FileFormat() == PARAVIEW) ||
13300  (config->GetOutput_FileFormat() == PARAVIEW_BINARY)){
13301  Variable_Names.push_back("Pressure_Coefficient");
13302  } else {
13303  Variable_Names.push_back("C<sub>p</sub>");
13304  }
13305 
13306  /*--- Add Laminar Viscosity, Skin Friction, and Heat Flux to the restart file ---*/
13307 
13308  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
13309  if ((config->GetOutput_FileFormat() == PARAVIEW) ||
13310  (config->GetOutput_FileFormat() == PARAVIEW_BINARY)){
13311  nVar_Par += 1; Variable_Names.push_back("Laminar_Viscosity");
13312  nVar_Par += 2;
13313  Variable_Names.push_back("Skin_Friction_Coefficient_x");
13314  Variable_Names.push_back("Skin_Friction_Coefficient_y");
13315  if (geometry->GetnDim() == 3) {
13316  nVar_Par += 1; Variable_Names.push_back("Skin_Friction_Coefficient_z");
13317  }
13318  if (energy || weakly_coupled_heat) {
13319  nVar_Par += 1;
13320  Variable_Names.push_back("Heat_Flux");
13321  }
13322  } else {
13323  nVar_Par += 1; Variable_Names.push_back("<greek>m</greek>");
13324  nVar_Par += 2;
13325  Variable_Names.push_back("C<sub>f</sub>_x");
13326  Variable_Names.push_back("C<sub>f</sub>_y");
13327  if (geometry->GetnDim() == 3) {
13328  nVar_Par += 1; Variable_Names.push_back("C<sub>f</sub>_z");
13329  }
13330  if (energy || weakly_coupled_heat) {
13331  nVar_Par += 1;
13332  Variable_Names.push_back("h");
13333  }
13334  }
13335  }
13336 
13337  /*--- Add Y+ and Eddy Viscosity. ---*/
13338 
13339  if (Kind_Solver == RANS) {
13340  nVar_Par += 2;
13341  if ((config->GetOutput_FileFormat() == PARAVIEW) ||
13342  (config->GetOutput_FileFormat() == PARAVIEW_BINARY)){
13343  Variable_Names.push_back("Y_Plus");
13344  Variable_Names.push_back("Eddy_Viscosity");
13345  } else {
13346  Variable_Names.push_back("y<sup>+</sup>");
13347  Variable_Names.push_back("<greek>m</greek><sub>t</sub>");
13348  }
13349  }
13350 
13351  /*--- Add the distance to the nearest sharp edge if requested. ---*/
13352 
13353  if (config->GetWrt_SharpEdges()) {
13354  nVar_Par += 1;
13355  Variable_Names.push_back("Sharp_Edge_Dist");
13356  }
13357 
13358  /*--- Add the intermittency for the BC trans. model. ---*/
13359 
13360  if (transition) {
13361  nVar_Par += 1;
13362  if ((config->GetOutput_FileFormat() == PARAVIEW) ||
13363  (config->GetOutput_FileFormat() == PARAVIEW_BINARY)){
13364  Variable_Names.push_back("gamma_BC");
13365  } else {
13366  Variable_Names.push_back("<greek>g</greek><sub>BC</sub>");
13367  }
13368  }
13369 
13370  /*--- New variables get registered here before the end of the loop. ---*/
13371 
13372  if (variable_density) {
13373  nVar_Par += 1;
13374  Variable_Names.push_back("Density");
13375  }
13376 
13377  }
13378 
13379  /*--- Auxiliary vectors for variables defined on surfaces only. ---*/
13380 
13381  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
13382  Aux_Frict_x = new su2double[geometry->GetnPoint()];
13383  Aux_Frict_y = new su2double[geometry->GetnPoint()];
13384  Aux_Frict_z = new su2double[geometry->GetnPoint()];
13385  Aux_Heat = new su2double[geometry->GetnPoint()];
13386  Aux_yPlus = new su2double[geometry->GetnPoint()];
13387 
13388  /*--- First, loop through the mesh in order to find and store the
13389  value of the viscous coefficients at any surface nodes. They
13390  will be placed in an auxiliary vector and then communicated like
13391  all other volumetric variables. ---*/
13392 
13393  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
13394  Aux_Frict_x[iPoint] = 0.0;
13395  Aux_Frict_y[iPoint] = 0.0;
13396  Aux_Frict_z[iPoint] = 0.0;
13397  Aux_Heat[iPoint] = 0.0;
13398  Aux_yPlus[iPoint] = 0.0;
13399  }
13400  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
13401  if (config->GetMarker_All_Plotting(iMarker) == YES) {
13402  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
13403  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
13404  Aux_Frict_x[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 0);
13405  Aux_Frict_y[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 1);
13406  if (geometry->GetnDim() == 3) Aux_Frict_z[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 2);
13407  Aux_Heat[iPoint] = solver[FLOW_SOL]->GetHeatFlux(iMarker, iVertex);
13408  Aux_yPlus[iPoint] = solver[FLOW_SOL]->GetYPlus(iMarker, iVertex);
13409  }
13410  }
13411  }
13412  }
13413 
13414  /*--- Allocate the local data structure now that we know how many
13415  variables are in the output. ---*/
13416 
13417  Local_Data = new su2double*[geometry->GetnPoint()];
13418  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
13419  Local_Data[iPoint] = new su2double[nVar_Par];
13420  }
13421 
13422  Local_Halo = new int[geometry->GetnPoint()];
13423  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
13424  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
13425 
13426  /*--- Search all send/recv boundaries on this partition for any periodic
13427  nodes that were part of the original domain. We want to recover these
13428  for visualization purposes. ---*/
13429 
13430  if (!Wrt_Halo) {
13431  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
13432  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
13433 
13434  /*--- Checking for less than or equal to the rank, because there may
13435  be some periodic halo nodes that send info to the same rank. ---*/
13436 
13437  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
13438  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
13439  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
13440  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
13441  if (isPeriodic) Local_Halo[iPoint] = false;
13442  }
13443  }
13444  }
13445  }
13446 
13447  /*--------------------------------------------------------------------------*/
13448  /*--- Step 2: Loop over all grid nodes and load up the desired data for ---*/
13449  /*--- the restart and vizualization files. Note that we need to ---*/
13450  /*--- increment the iVar variable after each variable load. ---*/
13451  /*--- The idea is that we're filling up the columns of field ---*/
13452  /*--- data for each iPoint (row) of the data structure. ---*/
13453  /*--- This data will then be sorted, communicated, and written ---*/
13454  /*--- to files automatically after this routine. Note that the ---*/
13455  /*--- ordering of the data loading MUST match the order of the ---*/
13456  /*--- variable registration above for the files to be correct. ---*/
13457  /*--------------------------------------------------------------------------*/
13458 
13459  jPoint = 0;
13460 
13461  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
13462 
13463  /*--- Check for halos & write only if requested ---*/
13464 
13465  if (!Local_Halo[iPoint] || Wrt_Halo) {
13466 
13467  /*--- Restart the column index with each new point. ---*/
13468 
13469  iVar = 0;
13470 
13471  /*--- Load the grid node coordinate values. ---*/
13472 
13473  for (iDim = 0; iDim < geometry->GetnDim(); iDim++) {
13474  Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetCoord(iDim); iVar++;
13475  }
13476 
13477  /*--- Load the conservative variable states for the mean flow variables. ---*/
13478 
13479  Local_Data[jPoint][iVar] = solver[FirstIndex]->node[iPoint]->GetSolution(0); iVar++;
13480  Local_Data[jPoint][iVar] = solver[FirstIndex]->node[iPoint]->GetSolution(1); iVar++;
13481  Local_Data[jPoint][iVar] = solver[FirstIndex]->node[iPoint]->GetSolution(2); iVar++;
13482  if (nDim == 3) {
13483  Local_Data[jPoint][iVar] = solver[FirstIndex]->node[iPoint]->GetSolution(3); iVar++;
13484  }
13485  if (weakly_coupled_heat) {
13486  Local_Data[jPoint][iVar] = solver[HEAT_SOL]->node[iPoint]->GetSolution(0);
13487  iVar++;
13488  } else if (energy) {
13489  Local_Data[jPoint][iVar] = solver[FirstIndex]->node[iPoint]->GetSolution(nDim+1);
13490  iVar++;
13491  }
13492 
13493  /*--- If this is RANS, i.e., the second solver container is not empty,
13494  then load data for the conservative turbulence variables. ---*/
13495 
13496  if (SecondIndex != NONE) {
13497  for (jVar = 0; jVar < nVar_Second; jVar++) {
13498  Local_Data[jPoint][iVar] = solver[SecondIndex]->node[iPoint]->GetSolution(jVar); iVar++;
13499  }
13500  }
13501 
13502  /*--- If limiters and/or residuals are requested. ---*/
13503  if (!config->GetLow_MemoryOutput()) {
13504 
13505  /*--- Limiters ---*/
13506  if (config->GetWrt_Limiters()) {
13507  /*--- Mean Flow Limiters ---*/
13508  for (jVar = 0; jVar < nVar_First; jVar++) {
13509  Local_Data[jPoint][iVar] = solver[FirstIndex]->node[iPoint]->GetLimiter_Primitive(jVar);
13510  iVar++;
13511  }
13512  /*--- RANS Limiters ---*/
13513  if (SecondIndex != NONE) {
13514  for (jVar = 0; jVar < nVar_Second; jVar++) {
13515  Local_Data[jPoint][iVar] = solver[SecondIndex]->node[iPoint]->GetLimiter_Primitive(jVar);
13516  iVar++;
13517  }
13518  }
13519  }
13520 
13521  /*--- Residuals ---*/
13522  if (config->GetWrt_Residuals()) {
13523  /*--- Mean Flow Residuals ---*/
13524  for (jVar = 0; jVar < nVar_First; jVar++) {
13525  Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes.GetBlock(iPoint, jVar);
13526  iVar++;
13527  }
13528  /*--- RANS Residuals ---*/
13529  if (SecondIndex != NONE) {
13530  for (jVar = 0; jVar < nVar_Second; jVar++) {
13531  Local_Data[jPoint][iVar] = solver[SecondIndex]->LinSysRes.GetBlock(iPoint, jVar);
13532  iVar++;
13533  }
13534  }
13535  }
13536  }
13537 
13538  if (!config->GetLow_MemoryOutput()) {
13539 
13540  /*--- Load buffers with the three grid velocity components. ---*/
13541 
13542  if (grid_movement) {
13543  Grid_Vel = geometry->node[iPoint]->GetGridVel();
13544  Local_Data[jPoint][iVar] = Grid_Vel[0]; iVar++;
13545  Local_Data[jPoint][iVar] = Grid_Vel[1]; iVar++;
13546  if (geometry->GetnDim() == 3) {
13547  Local_Data[jPoint][iVar] = Grid_Vel[2];
13548  iVar++;
13549  }
13550  }
13551 
13552  /*--- Load data for Cp and Mach variables. ---*/
13553 
13554  Local_Data[jPoint][iVar] = (solver[FLOW_SOL]->node[iPoint]->GetPressure() - RefPressure)*factor*RefArea; iVar++;
13555 
13556  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
13557 
13558  /*--- Load data for the laminar viscosity. ---*/
13559 
13560  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->node[iPoint]->GetLaminarViscosity(); iVar++;
13561 
13562  /*--- Load data for the skin friction, heat flux, and y-plus. ---*/
13563 
13564  Local_Data[jPoint][iVar] = Aux_Frict_x[iPoint]; iVar++;
13565  Local_Data[jPoint][iVar] = Aux_Frict_y[iPoint]; iVar++;
13566  if (geometry->GetnDim() == 3) {
13567  Local_Data[jPoint][iVar] = Aux_Frict_z[iPoint];
13568  iVar++;
13569  }
13570 
13571  if (energy || weakly_coupled_heat) {
13572  Local_Data[jPoint][iVar] = Aux_Heat[iPoint]; iVar++;
13573  }
13574 
13575  }
13576 
13577  /*--- Load data for the Eddy viscosity for RANS. ---*/
13578 
13579  if (Kind_Solver == RANS) {
13580  Local_Data[jPoint][iVar] = Aux_yPlus[iPoint]; iVar++;
13581  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->node[iPoint]->GetEddyViscosity(); iVar++;
13582  }
13583 
13584  /*--- Load data for the distance to the nearest sharp edge. ---*/
13585 
13586  if (config->GetWrt_SharpEdges()) {
13587  Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetSharpEdge_Distance(); iVar++;
13588  }
13589 
13590  /*--- Load data for the intermittency of the BC trans. model. ---*/
13591 
13592  if (transition) {
13593  Local_Data[jPoint][iVar] = solver[TURB_SOL]->node[iPoint]->GetGammaBC(); iVar++;
13594  }
13595 
13596  /*--- Load density if we are solving a variable density problem. ---*/
13597 
13598  if (variable_density) {
13599  Local_Data[jPoint][iVar] = solver[FLOW_SOL]->node[iPoint]->GetDensity(); iVar++;
13600  }
13601 
13602  /*--- New variables can be loaded to the Local_Data structure here,
13603  assuming they were registered above correctly. ---*/
13604 
13605  }
13606 
13607  /*--- Increment the point counter, as there may have been halos we
13608  skipped over during the data loading. ---*/
13609 
13610  jPoint++;
13611 
13612  }
13613  }
13614 
13615  /*--- Free memory for auxiliary vectors. ---*/
13616 
13617  if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) {
13618  delete [] Aux_Frict_x;
13619  delete [] Aux_Frict_y;
13620  delete [] Aux_Frict_z;
13621  delete [] Aux_Heat;
13622  delete [] Aux_yPlus;
13623  }
13624 
13625  delete [] Local_Halo;
13626 
13627 }
13628 
13629 void COutput::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
13630 
13631  unsigned short iDim;
13632  unsigned short Kind_Solver = config->GetKind_Solver();
13633  unsigned short nDim = geometry->GetnDim();
13634 
13635  unsigned long iVar, jVar;
13636  unsigned long iPoint, jPoint, FirstIndex = NONE, SecondIndex = NONE, iMarker, iVertex;
13637  unsigned long nVar_First = 0, nVar_Second = 0, nVar_Consv_Par = 0;
13638 
13639  su2double *Aux_Sens = NULL;
13640  su2double *Grid_Vel = NULL;
13641  su2double *Normal, Area;
13642 
13643  bool incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE);
13644  bool grid_movement = (config->GetGrid_Movement());
13645  bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
13646  bool transp = (config->GetnMarker_Transpiration() > 0);
13647 
13648  int *Local_Halo;
13649 
13650  stringstream varname;
13651 
13652  /*--- Use a switch statement to decide how many solver containers we have
13653  in this zone for output. ---*/
13654 
13655  switch (config->GetKind_Solver()) {
13656  case ADJ_EULER : case ADJ_NAVIER_STOKES : FirstIndex = ADJFLOW_SOL; SecondIndex = NONE; break;
13657  case ADJ_RANS : FirstIndex = ADJFLOW_SOL; if (config->GetFrozen_Visc_Cont()) SecondIndex = NONE; else SecondIndex = ADJTURB_SOL; break;
13658  case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: FirstIndex = ADJFLOW_SOL; SecondIndex = NONE; break;
13659  case DISC_ADJ_RANS: FirstIndex = ADJFLOW_SOL; if (config->GetFrozen_Visc_Disc()) SecondIndex = NONE; else SecondIndex = ADJTURB_SOL; break;
13660  }
13661 
13662  nVar_First = solver[FirstIndex]->GetnVar();
13663  if (SecondIndex != NONE) nVar_Second = solver[SecondIndex]->GetnVar();
13664  nVar_Consv_Par = nVar_First + nVar_Second;
13665 
13666  /*--------------------------------------------------------------------------*/
13667  /*--- Step 1: Register the variables that will be output. To register a ---*/
13668  /*--- variable, two things are required. First, increment the ---*/
13669  /*--- counter for the number of variables (nVar_Par), which ---*/
13670  /*--- controls the size of the data structure allocation, i.e., ---*/
13671  /*--- the number of columns in an nPoint x nVar structure. ---*/
13672  /*--- Second, add a name for the variable to the vector that ---*/
13673  /*--- holds the string names. ---*/
13674  /*--------------------------------------------------------------------------*/
13675 
13676  /*--- All output files first need the grid coordinates. ---*/
13677 
13678  nVar_Par = 1; Variable_Names.push_back("x");
13679  nVar_Par += 1; Variable_Names.push_back("y");
13680  if (geometry->GetnDim() == 3) {
13681  nVar_Par += 1; Variable_Names.push_back("z");
13682  }
13683 
13684  /*--- At a mininum, the restarts and visualization files need the
13685  conservative variables, so these follow next. ---*/
13686 
13687  nVar_Par += nVar_Consv_Par;
13688 
13689  /*--- For now, leave the names as "Conservative_", etc., in order
13690  to avoid confusion with the serial version, which still prints these
13691  names. Names can be set alternatively by using the commented code
13692  below. ---*/
13693 
13694  if (incompressible) {
13695  Variable_Names.push_back("Adjoint_Pressure");
13696  Variable_Names.push_back("Adjoint_Velocity_x");
13697  Variable_Names.push_back("Adjoint_Velocity_y");
13698  if (geometry->GetnDim() == 3) Variable_Names.push_back("Adjoint_Velocity_z");
13699  Variable_Names.push_back("Adjoint_Temperature");
13700  } else {
13701  Variable_Names.push_back("Adjoint_Density");
13702  Variable_Names.push_back("Adjoint_Momentum_x");
13703  Variable_Names.push_back("Adjoint_Momentum_y");
13704  if (geometry->GetnDim() == 3)
13705  Variable_Names.push_back("Adjoint_Momentum_z");
13706  Variable_Names.push_back("Adjoint_Energy");
13707  }
13708  if (SecondIndex != NONE) {
13709  if (config->GetKind_Turb_Model() == SST) {
13710  Variable_Names.push_back("Adjoint_TKE");
13711  Variable_Names.push_back("Adjoint_Omega");
13712  } else {
13713  /*--- S-A variants ---*/
13714  Variable_Names.push_back("Adjoint_Nu_Tilde");
13715  }
13716  }
13717 
13718  /*--- For the discrete adjoint, we have the full field of sensitivity
13719  in each coordinate direction. ---*/
13720 
13721  if ((Kind_Solver == DISC_ADJ_EULER) ||
13722  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
13723  (Kind_Solver == DISC_ADJ_RANS)) {
13724  nVar_Par += nDim;
13725  Variable_Names.push_back("Sensitivity_x");
13726  Variable_Names.push_back("Sensitivity_y");
13727  if (geometry->GetnDim()== 3)
13728  Variable_Names.push_back("Sensitivity_z");
13729  }
13730 
13731  /*--- For the discrete adjoint with transpiration boundary, we have the field of sensitivity
13732  wrt the transpiration velocity. ---*/
13733 
13734  if (transp && ((Kind_Solver == DISC_ADJ_EULER) ||
13735  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
13736  (Kind_Solver == DISC_ADJ_RANS))) {
13737  nVar_Par += 1;
13738  Variable_Names.push_back("Sensitivity_Transp");
13739  }
13740 
13741  /*--- If requested, register the limiter and residuals for all of the
13742  equations in the current flow problem. ---*/
13743 
13744  if (!config->GetLow_MemoryOutput()) {
13745 
13746  /*--- Add the limiters ---*/
13747 
13748  if (config->GetWrt_Limiters()) {
13749  nVar_Par += nVar_Consv_Par;
13750  if (incompressible) {
13751  Variable_Names.push_back("Limiter_Adjoint_Pressure");
13752  Variable_Names.push_back("Limiter_Adjoint_Velocity_x");
13753  Variable_Names.push_back("Limiter_Adjoint_Velocity_y");
13754  if (geometry->GetnDim() == 3) Variable_Names.push_back("Limiter_Adjoint_Velocity_z");
13755  Variable_Names.push_back("Limiter_Adjoint_Temperature");
13756  } else {
13757  Variable_Names.push_back("Limiter_Adjoint_Density");
13758  Variable_Names.push_back("Limiter_Adjoint_Momentum_x");
13759  Variable_Names.push_back("Limiter_Adjoint_Momentum_y");
13760  if (geometry->GetnDim() == 3)
13761  Variable_Names.push_back("Limiter_Adjoint_Momentum_z");
13762  Variable_Names.push_back("Limiter_Adjoint_Energy");
13763  }
13764  if (SecondIndex != NONE) {
13765  if (config->GetKind_Turb_Model() == SST) {
13766  Variable_Names.push_back("Limiter_Adjoint_TKE");
13767  Variable_Names.push_back("Limiter_Adjoint_Omega");
13768  } else {
13769  /*--- S-A variants ---*/
13770  Variable_Names.push_back("Limiter_Adjoint_Nu_Tilde");
13771  }
13772  }
13773  }
13774 
13775  /*--- Add the residuals ---*/
13776 
13777  if (config->GetWrt_Residuals()) {
13778  nVar_Par += nVar_Consv_Par;
13779  if (incompressible) {
13780  Variable_Names.push_back("Residual_Adjoint_Pressure");
13781  Variable_Names.push_back("Residual_Adjoint_Velocity_x");
13782  Variable_Names.push_back("Residual_Adjoint_Velocity_y");
13783  if (geometry->GetnDim() == 3) Variable_Names.push_back("Residual_Adjoint_Velocity_z");
13784  Variable_Names.push_back("Residual_Adjoint_Temperature");
13785  } else {
13786  Variable_Names.push_back("Residual_Adjoint_Density");
13787  Variable_Names.push_back("Residual_Adjoint_Momentum_x");
13788  Variable_Names.push_back("Residual_Adjoint_Momentum_y");
13789  if (geometry->GetnDim() == 3)
13790  Variable_Names.push_back("Residual_Adjoint_Momentum_z");
13791  Variable_Names.push_back("Residual_Adjoint_Energy");
13792  }
13793  if (SecondIndex != NONE) {
13794  if (config->GetKind_Turb_Model() == SST) {
13795  Variable_Names.push_back("Residual_Adjoint_TKE");
13796  Variable_Names.push_back("Residual_Adjoint_Omega");
13797  } else {
13798  /*--- S-A variants ---*/
13799  Variable_Names.push_back("Residual_Adjoint_Nu_Tilde");
13800  }
13801  }
13802  }
13803 
13804  /*--- Add the grid velocity. ---*/
13805 
13806  if (grid_movement) {
13807  if (geometry->GetnDim() == 2) nVar_Par += 2;
13808  else if (geometry->GetnDim() == 3) nVar_Par += 3;
13809  Variable_Names.push_back("Grid_Velocity_x");
13810  Variable_Names.push_back("Grid_Velocity_y");
13811  if (geometry->GetnDim() == 3) Variable_Names.push_back("Grid_Velocity_z");
13812  }
13813 
13814  /*--- All adjoint solvers write the surface sensitivity. ---*/
13815 
13816  nVar_Par += 1; Variable_Names.push_back("Surface_Sensitivity");
13817 
13818  /*--- For the continouus adjoint, we write either convective scheme's
13819  dissipation sensor (centered) or limiter (uwpind) for adj. density. ---*/
13820 
13821  if (( Kind_Solver == ADJ_EULER ) ||
13822  ( Kind_Solver == ADJ_NAVIER_STOKES ) ||
13823  ( Kind_Solver == ADJ_RANS )) {
13824  nVar_Par += 1;
13825  if (config->GetKind_ConvNumScheme() == SPACE_CENTERED) {
13826  Variable_Names.push_back("Dissipation_Sensor");
13827  } else {
13828  Variable_Names.push_back("Limiter_Adjoint_Density");
13829  }
13830  }
13831 
13832  /*--- New variables get registered here before the end of the loop. ---*/
13833 
13834  }
13835 
13836  /*--- Auxiliary vectors for variables defined on surfaces only. ---*/
13837 
13838  Aux_Sens = new su2double[geometry->GetnPoint()];
13839 
13840  /*--- First, loop through the mesh in order to find and store the
13841  value of the viscous coefficients at any surface nodes. They
13842  will be placed in an auxiliary vector and then communicated like
13843  all other volumetric variables. ---*/
13844 
13845  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
13846  Aux_Sens[iPoint] = 0.0;
13847  }
13848  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++)
13849  if (config->GetMarker_All_Plotting(iMarker) == YES) {
13850  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
13851  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
13852  Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
13853  Area = 0.0;
13854  for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim];
13855  Area = sqrt (Area);
13856  Aux_Sens[iPoint] = solver[ADJFLOW_SOL]->GetCSensitivity(iMarker, iVertex)/Area;
13857  }
13858  }
13859 
13860  /*--- Allocate the local data structure now that we know how many
13861  variables are in the output. ---*/
13862 
13863  Local_Data = new su2double*[geometry->GetnPoint()];
13864  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
13865  Local_Data[iPoint] = new su2double[nVar_Par];
13866  }
13867 
13868  Local_Halo = new int[geometry->GetnPoint()];
13869  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
13870  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
13871 
13872  /*--- Search all send/recv boundaries on this partition for any periodic
13873  nodes that were part of the original domain. We want to recover these
13874  for visualization purposes. ---*/
13875 
13876  if (!Wrt_Halo) {
13877  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
13878  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
13879 
13880  /*--- Checking for less than or equal to the rank, because there may
13881  be some periodic halo nodes that send info to the same rank. ---*/
13882 
13883  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
13884  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
13885  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
13886  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
13887  if (isPeriodic) Local_Halo[iPoint] = false;
13888  }
13889  }
13890  }
13891  }
13892 
13893  /*--------------------------------------------------------------------------*/
13894  /*--- Step 2: Loop over all grid nodes and load up the desired data for ---*/
13895  /*--- the restart and vizualization files. Note that we need to ---*/
13896  /*--- increment the iVar variable after each variable load. ---*/
13897  /*--- The idea is that we're filling up the columns of field ---*/
13898  /*--- data for each iPoint (row) of the data structure. This ---*/
13899  /*--- This data will then be sorted, communicated, and written ---*/
13900  /*--- to files automatically after this routine. Note that the ---*/
13901  /*--- ordering of the data loading MUST match the order of the ---*/
13902  /*--- variable registration above for the files to be correct. ---*/
13903  /*--------------------------------------------------------------------------*/
13904 
13905  jPoint = 0;
13906 
13907  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
13908 
13909  /*--- Check for halos & write only if requested ---*/
13910 
13911  if (!Local_Halo[iPoint] || Wrt_Halo) {
13912 
13913  /*--- Restart the column index with each new point. ---*/
13914 
13915  iVar = 0;
13916 
13917  /*--- Load the grid node coordinate values. ---*/
13918 
13919  for (iDim = 0; iDim < geometry->GetnDim(); iDim++) {
13920  Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetCoord(iDim);
13921  if (config->GetSystemMeasurements() == US)
13922  Local_Data[jPoint][iVar] *= 12.0;
13923  iVar++;
13924  }
13925 
13926  /*--- Load the conservative variable states for the mean flow variables.
13927  If requested, load the limiters and residuals as well. ---*/
13928 
13929  for (jVar = 0; jVar < nVar_First; jVar++) {
13930  Local_Data[jPoint][iVar] = solver[FirstIndex]->node[iPoint]->GetSolution(jVar);
13931  iVar++;
13932  }
13933 
13934 
13935  /*--- If this is Adj. RANS, i.e., the second solver container is not empty,
13936  then load data for the conservative turbulence variables and the
13937  limiters / residuals (if requested). ----*/
13938 
13939  if (SecondIndex != NONE) {
13940  for (jVar = 0; jVar < nVar_Second; jVar++) {
13941  Local_Data[jPoint][iVar] = solver[SecondIndex]->node[iPoint]->GetSolution(jVar);
13942  iVar++;
13943  }
13944  }
13945 
13946  /*--- Load data for the discrete sensitivities. ---*/
13947 
13948  if ((Kind_Solver == DISC_ADJ_EULER) ||
13949  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
13950  (Kind_Solver == DISC_ADJ_RANS)) {
13951  Local_Data[jPoint][iVar] = solver[ADJFLOW_SOL]->node[iPoint]->GetSensitivity(0); iVar++;
13952  Local_Data[jPoint][iVar] = solver[ADJFLOW_SOL]->node[iPoint]->GetSensitivity(1); iVar++;
13953  if (geometry->GetnDim()== 3) {
13954  Local_Data[jPoint][iVar] = solver[ADJFLOW_SOL]->node[iPoint]->GetSensitivity(2);
13955  iVar++;
13956  }
13957  }
13958 
13959  /*--- Load data for the transpiration sensitivities. ---*/
13960 
13961  if (transp && ((Kind_Solver == DISC_ADJ_EULER) ||
13962  (Kind_Solver == DISC_ADJ_NAVIER_STOKES) ||
13963  (Kind_Solver == DISC_ADJ_RANS))) {
13964  Local_Data[jPoint][iVar] = solver[ADJFLOW_SOL]->node[iPoint]->GetSensitivityTranspiration(); iVar++;
13965  }
13966 
13967  if (!config->GetLow_MemoryOutput()) {
13968 
13969  if (config->GetWrt_Limiters()) {
13970  for (jVar = 0; jVar < nVar_First; jVar++) {
13971  Local_Data[jPoint][iVar] = solver[FirstIndex]->node[iPoint]->GetLimiter(jVar);
13972  iVar++;
13973  }
13974  if (SecondIndex != NONE) {
13975  for (jVar = 0; jVar < nVar_Second; jVar++) {
13976  Local_Data[jPoint][iVar] = solver[SecondIndex]->node[iPoint]->GetLimiter(jVar);
13977  iVar++;
13978  }
13979  }
13980  }
13981 
13982  if (config->GetWrt_Residuals()) {
13983  for (jVar = 0; jVar < nVar_First; jVar++) {
13984  if (!config->GetDiscrete_Adjoint()) {
13985  Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes.GetBlock(iPoint, jVar);
13986  } else {
13987  Local_Data[jPoint][iVar] = solver[FirstIndex]->node[iPoint]->GetSolution(jVar) -
13988  solver[FirstIndex]->node[iPoint]->GetSolution_Old(jVar);
13989  }
13990  iVar++;
13991  }
13992  if (SecondIndex != NONE) {
13993  for (jVar = 0; jVar < nVar_Second; jVar++) {
13994  if (!config->GetDiscrete_Adjoint()) {
13995  Local_Data[jPoint][iVar] = solver[SecondIndex]->LinSysRes.GetBlock(iPoint, jVar);
13996  } else {
13997  Local_Data[jPoint][iVar] = solver[SecondIndex]->node[iPoint]->GetSolution(jVar) -
13998  solver[SecondIndex]->node[iPoint]->GetSolution_Old(jVar);
13999  }
14000  iVar++;
14001  }
14002  }
14003  }
14004 
14005  /*--- Load buffers with the three grid velocity components. ---*/
14006 
14007  if (grid_movement) {
14008  Grid_Vel = geometry->node[iPoint]->GetGridVel();
14009  Local_Data[jPoint][iVar] = Grid_Vel[0]; iVar++;
14010  Local_Data[jPoint][iVar] = Grid_Vel[1]; iVar++;
14011  if (geometry->GetnDim() == 3) {
14012  Local_Data[jPoint][iVar] = Grid_Vel[2];
14013  iVar++;
14014  }
14015  }
14016 
14017  /*--- Load data for the surface sensitivity. ---*/
14018 
14019  Local_Data[iPoint][iVar] = Aux_Sens[iPoint]; iVar++;
14020 
14021  /*--- Load data for the convective scheme sensor. ---*/
14022 
14023  if (( Kind_Solver == ADJ_EULER ) ||
14024  ( Kind_Solver == ADJ_NAVIER_STOKES ) ||
14025  ( Kind_Solver == ADJ_RANS )) {
14026  if (config->GetKind_ConvNumScheme() == SPACE_CENTERED) {
14027  Local_Data[jPoint][iVar] = solver[ADJFLOW_SOL]->node[iPoint]->GetSensor(iPoint); iVar++;
14028  } else {
14029  Local_Data[jPoint][iVar] = solver[ADJFLOW_SOL]->node[iPoint]->GetLimiter(0); iVar++;
14030  }
14031  }
14032 
14033  /*--- New variables can be loaded to the Local_Data structure here,
14034  assuming they were registered above correctly. ---*/
14035 
14036  }
14037 
14038  /*--- Increment the point counter, as there may have been halos we
14039  skipped over during the data loading. ---*/
14040 
14041  jPoint++;
14042  }
14043  }
14044 
14045  /*--- Free memory for auxiliary vectors. ---*/
14046 
14047  delete [] Aux_Sens;
14048  delete [] Local_Halo;
14049 
14050 }
14051 
14052 void COutput::LoadLocalData_Elasticity(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
14053 
14054  unsigned short iDim;
14055 
14056  unsigned long iVar, jVar;
14057  unsigned long iPoint, jPoint, FirstIndex = NONE, iMarker, iVertex;
14058  unsigned long nVar_First = 0, nVar_Consv_Par = 0;
14059 
14060  su2double *Node_Vel = NULL, *Node_Accel = NULL, *Stress = NULL;
14061 
14062  bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
14063  int *Local_Halo = NULL;
14064 
14065  stringstream varname;
14066 
14067  /*--- Use a switch statement to decide how many solver containers we have
14068  in this zone for output. ---*/
14069 
14070  switch (config->GetKind_Solver()) {
14071  case FEM_ELASTICITY: FirstIndex = FEA_SOL; break;
14072  case DISC_ADJ_FEM: FirstIndex = ADJFEA_SOL; break;
14073  }
14074 
14075  nVar_First = solver[FirstIndex]->GetnVar();
14076  nVar_Consv_Par = nVar_First;
14077 
14078  /*--------------------------------------------------------------------------*/
14079  /*--- Step 1: Register the variables that will be output. To register a ---*/
14080  /*--- variable, two things are required. First, increment the ---*/
14081  /*--- counter for the number of variables (nVar_Par), which ---*/
14082  /*--- controls the size of the data structure allocation, i.e., ---*/
14083  /*--- the number of columns in an nPoint x nVar structure. ---*/
14084  /*--- Second, add a name for the variable to the vector that ---*/
14085  /*--- holds the string names. ---*/
14086  /*--------------------------------------------------------------------------*/
14087 
14088  /*--- All output files first need the grid coordinates. ---*/
14089 
14090  nVar_Par = 1; Variable_Names.push_back("x");
14091  nVar_Par += 1; Variable_Names.push_back("y");
14092  if (geometry->GetnDim() == 3) {
14093  nVar_Par += 1; Variable_Names.push_back("z");
14094  }
14095 
14096  /*--- At a mininum, the restarts and visualization files need the
14097  conservative variables, so these follow next. ---*/
14098 
14099  nVar_Par += nVar_Consv_Par;
14100 
14101  /*--- For now, leave the names as "Conservative_", etc., in order
14102  to avoid confusion with the serial version, which still prints these
14103  names. Names can be set alternatively by using the commented code
14104  below. ---*/
14105 
14106  Variable_Names.push_back("Displacement_x");
14107  Variable_Names.push_back("Displacement_y");
14108  if (geometry->GetnDim() == 3)
14109  Variable_Names.push_back("Displacement_z");
14110 
14111  /*--- If requested, register the limiter and residuals for all of the
14112  equations in the current flow problem. ---*/
14113 
14114  if (!config->GetLow_MemoryOutput()) {
14115 
14116  /*--- Add the residuals ---*/
14117 
14118  if (config->GetWrt_Residuals()) {
14119  nVar_Par += nVar_Consv_Par;
14120  Variable_Names.push_back("Residual_Displacement_x");
14121  Variable_Names.push_back("Residual_Displacement_y");
14122  if (geometry->GetnDim() == 3)
14123  Variable_Names.push_back("Residual_Displacement_z");
14124  }
14125 
14126  /*--- If the analysis is dynamic... ---*/
14127  if (config->GetDynamic_Analysis() == DYNAMIC) {
14128 
14129  /*--- Velocities ---*/
14130  nVar_Par += 2;
14131  Variable_Names.push_back("Velocity_x");
14132  Variable_Names.push_back("Velocity_y");
14133  if (geometry->GetnDim() == 3) {
14134  nVar_Par += 1;
14135  Variable_Names.push_back("Velocity_z");
14136  }
14137 
14138  /*--- Accelerations ---*/
14139  nVar_Par += 2;
14140  Variable_Names.push_back("Acceleration_x");
14141  Variable_Names.push_back("Acceleration_y");
14142  if (geometry->GetnDim() == 3) {
14143  nVar_Par += 1;
14144  Variable_Names.push_back("Acceleration_z");
14145  }
14146  }
14147 
14148  if (!(config->GetDiscrete_Adjoint())) {
14149 
14150  /*--- Add the stresses. ---*/
14151 
14152  nVar_Par += 3;
14153  Variable_Names.push_back("Sxx");
14154  Variable_Names.push_back("Syy");
14155  Variable_Names.push_back("Sxy");
14156  if (geometry->GetnDim() == 3) {
14157  nVar_Par += 3;
14158  Variable_Names.push_back("Szz");
14159  Variable_Names.push_back("Sxz");
14160  Variable_Names.push_back("Syz");
14161  }
14162 
14163  /*--- Add the Von Mises Stress. ---*/
14164 
14165  nVar_Par += 1;
14166  Variable_Names.push_back("Von_Mises_Stress");
14167 
14168  }
14169 
14170  /*--- New variables get registered here before the end of the loop. ---*/
14171 
14172  }
14173 
14174  /*--- Allocate the local data structure now that we know how many
14175  variables are in the output. ---*/
14176 
14177  Local_Data = new su2double*[geometry->GetnPoint()];
14178  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
14179  Local_Data[iPoint] = new su2double[nVar_Par];
14180  }
14181 
14182  Local_Halo = new int[geometry->GetnPoint()];
14183  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
14184  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
14185 
14186  /*--- Search all send/recv boundaries on this partition for any periodic
14187  nodes that were part of the original domain. We want to recover these
14188  for visualization purposes. ---*/
14189 
14190  if (!Wrt_Halo) {
14191  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
14192  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
14193 
14194  /*--- Checking for less than or equal to the rank, because there may
14195  be some periodic halo nodes that send info to the same rank. ---*/
14196 
14197  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
14198  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
14199  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
14200  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
14201  if (isPeriodic) Local_Halo[iPoint] = false;
14202  }
14203  }
14204  }
14205  }
14206 
14207  /*--------------------------------------------------------------------------*/
14208  /*--- Step 2: Loop over all grid nodes and load up the desired data for ---*/
14209  /*--- the restart and vizualization files. Note that we need to ---*/
14210  /*--- increment the iVar variable after each variable load. ---*/
14211  /*--- The idea is that we're filling up the columns of field ---*/
14212  /*--- data for each iPoint (row) of the data structure. This ---*/
14213  /*--- This data will then be sorted, communicated, and written ---*/
14214  /*--- to files automatically after this routine. Note that the ---*/
14215  /*--- ordering of the data loading MUST match the order of the ---*/
14216  /*--- variable registration above for the files to be correct. ---*/
14217  /*--------------------------------------------------------------------------*/
14218 
14219  jPoint = 0;
14220 
14221  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
14222 
14223  /*--- Check for halos & write only if requested ---*/
14224 
14225  if (!Local_Halo[iPoint] || Wrt_Halo) {
14226 
14227  /*--- Restart the column index with each new point. ---*/
14228 
14229  iVar = 0;
14230 
14231  /*--- Load the grid node coordinate values. ---*/
14232 
14233  for (iDim = 0; iDim < geometry->GetnDim(); iDim++) {
14234  Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetCoord(iDim);
14235  if (config->GetSystemMeasurements() == US)
14236  Local_Data[jPoint][iVar] *= 12.0;
14237  iVar++;
14238  }
14239 
14240  /*--- Load the conservative variable states for the mean flow variables.
14241  If requested, load the limiters and residuals as well. ---*/
14242 
14243  for (jVar = 0; jVar < nVar_First; jVar++) {
14244  Local_Data[jPoint][iVar] = solver[FirstIndex]->node[iPoint]->GetSolution(jVar);
14245  iVar++;
14246  }
14247 
14248  if (!config->GetLow_MemoryOutput()) {
14249  if (config->GetWrt_Residuals()) {
14250  for (jVar = 0; jVar < nVar_First; jVar++) {
14251  Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes.GetBlock(iPoint, jVar);
14252  iVar++;
14253  }
14254  }
14255  }
14256 
14257  if (!config->GetLow_MemoryOutput()) {
14258 
14259  /*--- Load the velocities and accelerations (dynamic calculations). ---*/
14260 
14261  if (config->GetDynamic_Analysis() == DYNAMIC) {
14262 
14263  /*--- Velocities ---*/
14264 
14265  Node_Vel = solver[FEA_SOL]->node[iPoint]->GetSolution_Vel();
14266  Local_Data[jPoint][iVar] = Node_Vel[0]; iVar++;
14267  Local_Data[jPoint][iVar] = Node_Vel[1]; iVar++;
14268  if (geometry->GetnDim() == 3) {
14269  Local_Data[jPoint][iVar] = Node_Vel[2];
14270  iVar++;
14271  }
14272 
14273  /*--- Accelerations ---*/
14274 
14275  Node_Accel = solver[FEA_SOL]->node[iPoint]->GetSolution_Accel();
14276  Local_Data[jPoint][iVar] = Node_Accel[0]; iVar++;
14277  Local_Data[jPoint][iVar] = Node_Accel[1]; iVar++;
14278  if (geometry->GetnDim() == 3) {
14279  Local_Data[jPoint][iVar] = Node_Accel[2];
14280  iVar++;
14281  }
14282  }
14283 
14284  if (!(config->GetDiscrete_Adjoint())) {
14285 
14286  /*--- Add the stresses. ---*/
14287 
14288  Stress = solver[FEA_SOL]->node[iPoint]->GetStress_FEM();
14289 
14290  /*--- Sigma xx ---*/
14291  Local_Data[jPoint][iVar] = Stress[0]; iVar++;
14292  /*--- Sigma yy ---*/
14293  Local_Data[jPoint][iVar] = Stress[1]; iVar++;
14294  /*--- Sigma xy ---*/
14295  Local_Data[jPoint][iVar] = Stress[2]; iVar++;
14296 
14297  if (geometry->GetnDim() == 3) {
14298  /*--- Sigma zz ---*/
14299  Local_Data[jPoint][iVar] = Stress[3]; iVar++;
14300  /*--- Sigma xz ---*/
14301  Local_Data[jPoint][iVar] = Stress[4]; iVar++;
14302  /*--- Sigma yz ---*/
14303  Local_Data[jPoint][iVar] = Stress[5]; iVar++;
14304  }
14305 
14306  /*--- Add the Von Mises Stress. ---*/
14307 
14308  Local_Data[iPoint][iVar] = solver[FEA_SOL]->node[iPoint]->GetVonMises_Stress(); iVar++;
14309 
14310 
14311  /*--- New variables can be loaded to the Local_Data structure here,
14312  assuming they were registered above correctly. ---*/
14313 
14314  }
14315 
14316  }
14317 
14318  /*--- Increment the point counter, as there may have been halos we
14319  skipped over during the data loading. ---*/
14320 
14321  jPoint++;
14322  }
14323  }
14324 
14325  /*--- Free memory for auxiliary vectors. ---*/
14326 
14327  delete [] Local_Halo;
14328 
14329 }
14330 
14331 void COutput::LoadLocalData_Base(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
14332 
14333  unsigned short iDim;
14334 
14335  unsigned long iVar, jVar;
14336  unsigned long iPoint, jPoint, FirstIndex = NONE, iMarker, iVertex;
14337  unsigned long nVar_First = 0, nVar_Consv_Par = 0;
14338 
14339  bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic;
14340 
14341  int *Local_Halo;
14342 
14343  stringstream varname;
14344 
14345  /*--- Use a switch statement to decide how many solver containers we have
14346  in this zone for output. ---*/
14347 
14348  switch (config->GetKind_Solver()) {
14349  case HEAT_EQUATION_FVM: FirstIndex = HEAT_SOL; break;
14350  }
14351 
14352  nVar_First = solver[FirstIndex]->GetnVar();
14353  nVar_Consv_Par = nVar_First;
14354 
14355  /*--------------------------------------------------------------------------*/
14356  /*--- Step 1: Register the variables that will be output. To register a ---*/
14357  /*--- variable, two things are required. First, increment the ---*/
14358  /*--- counter for the number of variables (nVar_Par), which ---*/
14359  /*--- controls the size of the data structure allocation, i.e., ---*/
14360  /*--- the number of columns in an nPoint x nVar structure. ---*/
14361  /*--- Second, add a name for the variable to the vector that ---*/
14362  /*--- holds the string names. ---*/
14363  /*--------------------------------------------------------------------------*/
14364 
14365  /*--- All output files first need the grid coordinates. ---*/
14366 
14367  nVar_Par = 1; Variable_Names.push_back("x");
14368  nVar_Par += 1; Variable_Names.push_back("y");
14369  if (geometry->GetnDim() == 3) {
14370  nVar_Par += 1; Variable_Names.push_back("z");
14371  }
14372 
14373  /*--- At a mininum, the restarts and visualization files need the
14374  conservative variables, so these follow next. ---*/
14375 
14376  nVar_Par += nVar_Consv_Par;
14377  for (iVar = 0; iVar < nVar_Consv_Par; iVar++) {
14378  varname << "Conservative_" << iVar+1;
14379  Variable_Names.push_back(varname.str());
14380  varname.str("");
14381  }
14382 
14383  /*--- If requested, register the residuals for all of the
14384  equations in the current problem. ---*/
14385 
14386  if (!config->GetLow_MemoryOutput()) {
14387 
14388  /*--- Add the residuals ---*/
14389 
14390  if (config->GetWrt_Residuals()) {
14391  nVar_Par += nVar_Consv_Par;
14392  for (iVar = 0; iVar < nVar_Consv_Par; iVar++) {
14393  varname << "Residual_" << iVar+1;
14394  Variable_Names.push_back(varname.str());
14395  varname.str("");
14396  }
14397  }
14398 
14399  /*--- New variables get registered here before the end of the loop. ---*/
14400 
14401  }
14402 
14403  /*--- Allocate the local data structure now that we know how many
14404  variables are in the output. ---*/
14405 
14406  Local_Data = new su2double*[geometry->GetnPoint()];
14407  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
14408  Local_Data[iPoint] = new su2double[nVar_Par];
14409  }
14410 
14411  Local_Halo = new int[geometry->GetnPoint()];
14412  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
14413  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
14414 
14415  /*--- Search all send/recv boundaries on this partition for any periodic
14416  nodes that were part of the original domain. We want to recover these
14417  for visualization purposes. ---*/
14418 
14419  if (!Wrt_Halo) {
14420  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
14421  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
14422 
14423  /*--- Checking for less than or equal to the rank, because there may
14424  be some periodic halo nodes that send info to the same rank. ---*/
14425 
14426  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
14427  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
14428  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
14429  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
14430  if (isPeriodic) Local_Halo[iPoint] = false;
14431  }
14432  }
14433  }
14434  }
14435 
14436  /*--------------------------------------------------------------------------*/
14437  /*--- Step 2: Loop over all grid nodes and load up the desired data for ---*/
14438  /*--- the restart and vizualization files. Note that we need to ---*/
14439  /*--- increment the iVar variable after each variable load. ---*/
14440  /*--- The idea is that we're filling up the columns of field ---*/
14441  /*--- data for each iPoint (row) of the data structure. This ---*/
14442  /*--- This data will then be sorted, communicated, and written ---*/
14443  /*--- to files automatically after this routine. Note that the ---*/
14444  /*--- ordering of the data loading MUST match the order of the ---*/
14445  /*--- variable registration above for the files to be correct. ---*/
14446  /*--------------------------------------------------------------------------*/
14447 
14448  jPoint = 0;
14449 
14450  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
14451 
14452  /*--- Check for halos & write only if requested ---*/
14453 
14454  if (!Local_Halo[iPoint] || Wrt_Halo) {
14455 
14456  /*--- Restart the column index with each new point. ---*/
14457 
14458  iVar = 0;
14459 
14460  /*--- Load the grid node coordinate values. ---*/
14461 
14462  for (iDim = 0; iDim < geometry->GetnDim(); iDim++) {
14463  Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetCoord(iDim);
14464  if (config->GetSystemMeasurements() == US)
14465  Local_Data[jPoint][iVar] *= 12.0;
14466  iVar++;
14467  }
14468 
14469  /*--- Load the conservative variable states for the mean flow variables.
14470  If requested, load the limiters and residuals as well. ---*/
14471 
14472  for (jVar = 0; jVar < nVar_First; jVar++) {
14473  Local_Data[jPoint][iVar] = solver[FirstIndex]->node[iPoint]->GetSolution(jVar);
14474  iVar++;
14475  }
14476 
14477  if (!config->GetLow_MemoryOutput()) {
14478  if (config->GetWrt_Residuals()) {
14479  for (jVar = 0; jVar < nVar_First; jVar++) {
14480  Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes.GetBlock(iPoint, jVar);
14481  iVar++;
14482  }
14483  }
14484  }
14485 
14486  /*--- New variables can be loaded to the Local_Data structure here,
14487  assuming they were registered above correctly. ---*/
14488 
14489  /*--- Increment the point counter, as there may have been halos we
14490  skipped over during the data loading. ---*/
14491 
14492  jPoint++;
14493 
14494  }
14495  }
14496 
14497  /*--- Free memory for auxiliary vectors. ---*/
14498 
14499  delete [] Local_Halo;
14500 
14501 }
14502 
14503 void COutput::SortConnectivity(CConfig *config, CGeometry *geometry, unsigned short val_iZone) {
14504 
14505  /*--- Flags identifying the types of files to be written. ---*/
14506 
14507  bool Wrt_Vol = config->GetWrt_Vol_Sol();
14508  bool Wrt_Srf = config->GetWrt_Srf_Sol();
14509 
14510  /*--- Sort connectivity for each type of element (excluding halos). Note
14511  In these routines, we sort the connectivity into a linear partitioning
14512  across all processors based on the global index of the grid nodes. ---*/
14513 
14514  /*--- Sort volumetric grid connectivity. ---*/
14515 
14516  if (Wrt_Vol) {
14517 
14518  if ((rank == MASTER_NODE) && (size != SINGLE_NODE))
14519  cout <<"Sorting volumetric grid connectivity." << endl;
14520 
14521  SortVolumetricConnectivity(config, geometry, TRIANGLE );
14522  SortVolumetricConnectivity(config, geometry, QUADRILATERAL);
14523  SortVolumetricConnectivity(config, geometry, TETRAHEDRON );
14524  SortVolumetricConnectivity(config, geometry, HEXAHEDRON );
14525  SortVolumetricConnectivity(config, geometry, PRISM );
14526  SortVolumetricConnectivity(config, geometry, PYRAMID );
14527 
14528  }
14529 
14530  /*--- Sort surface grid connectivity. ---*/
14531 
14532  if (Wrt_Srf) {
14533 
14534  if ((rank == MASTER_NODE) && (size != SINGLE_NODE))
14535  cout <<"Sorting surface grid connectivity." << endl;
14536 
14537  SortSurfaceConnectivity(config, geometry, LINE );
14538  SortSurfaceConnectivity(config, geometry, TRIANGLE );
14539  SortSurfaceConnectivity(config, geometry, QUADRILATERAL);
14540 
14541  }
14542 
14543  /*--- Reduce the total number of cells we will be writing in the output files. ---*/
14544 
14545  unsigned long nTotal_Elem = nParallel_Tria + nParallel_Quad + nParallel_Tetr + nParallel_Hexa + nParallel_Pris + nParallel_Pyra;
14546  unsigned long nTotal_Surf_Elem = nParallel_Line + nParallel_BoundTria + nParallel_BoundQuad;
14547 #ifndef HAVE_MPI
14548  nGlobal_Elem_Par = nTotal_Elem;
14549  nSurf_Elem_Par = nTotal_Surf_Elem;
14550 #else
14551  SU2_MPI::Allreduce(&nTotal_Elem, &nGlobal_Elem_Par, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
14552  SU2_MPI::Allreduce(&nTotal_Surf_Elem, &nSurf_Elem_Par, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
14553 #endif
14554 
14555 }
14556 
14557 void COutput::SortVolumetricConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) {
14558 
14559  unsigned long iProcessor;
14560  unsigned short NODES_PER_ELEMENT = 0;
14561  unsigned long iPoint, jPoint, kPoint, nLocalPoint, nTotalPoint;
14562  unsigned long nElem_Total = 0, Global_Index;
14563 
14564  unsigned long iVertex, iMarker;
14565  int SendRecv, RecvFrom;
14566 
14567  bool notPeriodic, notHalo, addedPeriodic, isPeriodic;
14568 
14569  int *Local_Halo = NULL;
14570  int *Conn_Elem = NULL;
14571 
14572 #ifdef HAVE_MPI
14573  SU2_MPI::Request *send_req, *recv_req;
14574  SU2_MPI::Status status;
14575  int ind;
14576 #endif
14577 
14578  /*--- Store the local number of this element type and the number of nodes
14579  per this element type. In serial, this will be the total number of this
14580  element type in the entire mesh. In parallel, it is the number on only
14581  the current partition. ---*/
14582 
14583  switch (Elem_Type) {
14584  case TRIANGLE:
14585  NODES_PER_ELEMENT = N_POINTS_TRIANGLE;
14586  break;
14587  case QUADRILATERAL:
14588  NODES_PER_ELEMENT = N_POINTS_QUADRILATERAL;
14589  break;
14590  case TETRAHEDRON:
14591  NODES_PER_ELEMENT = N_POINTS_TETRAHEDRON;
14592  break;
14593  case HEXAHEDRON:
14594  NODES_PER_ELEMENT = N_POINTS_HEXAHEDRON;
14595  break;
14596  case PRISM:
14597  NODES_PER_ELEMENT = N_POINTS_PRISM;
14598  break;
14599  case PYRAMID:
14600  NODES_PER_ELEMENT = N_POINTS_PYRAMID;
14601  break;
14602  default:
14603  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
14604  }
14605 
14606  /*--- Force the removal of all added periodic elements (use global index).
14607  First, we isolate and create a list of all added periodic points, excluding
14608  those that were part of the original domain (we want these to be in the
14609  output files). ---*/
14610 
14611  vector<unsigned long> Added_Periodic;
14612  Added_Periodic.clear();
14613 
14614  if (config->GetKind_SU2() != SU2_DEF) {
14615  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
14616  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
14617  SendRecv = config->GetMarker_All_SendRecv(iMarker);
14618  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
14619  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
14620 
14621  if ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
14622  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 0) &&
14623  (SendRecv < 0)) {
14624  Added_Periodic.push_back(geometry->node[iPoint]->GetGlobalIndex());
14625  }
14626  }
14627  }
14628  }
14629  }
14630 
14631  /*--- Now we communicate this information to all processors, so that they
14632  can force the removal of these particular nodes by flagging them as halo
14633  points. In general, this should be a small percentage of the total mesh,
14634  so the communication/storage costs here shouldn't be prohibitive. ---*/
14635 
14636  /*--- First communicate the number of points that each rank has found. ---*/
14637 
14638  unsigned long nAddedPeriodic = 0, maxAddedPeriodic = 0;
14639  unsigned long Buffer_Send_nAddedPeriodic[1], *Buffer_Recv_nAddedPeriodic = NULL;
14640  Buffer_Recv_nAddedPeriodic = new unsigned long[size];
14641 
14642  nAddedPeriodic = Added_Periodic.size();
14643  Buffer_Send_nAddedPeriodic[0] = nAddedPeriodic;
14644 
14645 #ifdef HAVE_MPI
14646  SU2_MPI::Allreduce(&nAddedPeriodic, &maxAddedPeriodic, 1, MPI_UNSIGNED_LONG,
14648  SU2_MPI::Allgather(&Buffer_Send_nAddedPeriodic, 1, MPI_UNSIGNED_LONG,
14649  Buffer_Recv_nAddedPeriodic, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
14650 #else
14651  maxAddedPeriodic = nAddedPeriodic;
14652  Buffer_Recv_nAddedPeriodic[0] = Buffer_Send_nAddedPeriodic[0];
14653 #endif
14654 
14655  /*--- Communicate the global index values of all added periodic nodes. ---*/
14656  unsigned long *Buffer_Send_AddedPeriodic = new unsigned long[maxAddedPeriodic];
14657  unsigned long *Buffer_Recv_AddedPeriodic = new unsigned long[size*maxAddedPeriodic];
14658 
14659  for (iPoint = 0; iPoint < Added_Periodic.size(); iPoint++) {
14660  Buffer_Send_AddedPeriodic[iPoint] = Added_Periodic[iPoint];
14661  }
14662 
14663  /*--- Gather the element connectivity information. All processors will now
14664  have a copy of the global index values for all added periodic points. ---*/
14665 
14666 #ifdef HAVE_MPI
14667  SU2_MPI::Allgather(Buffer_Send_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
14668  Buffer_Recv_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
14669  MPI_COMM_WORLD);
14670 #else
14671  for (iPoint = 0; iPoint < maxAddedPeriodic; iPoint++)
14672  Buffer_Recv_AddedPeriodic[iPoint] = Buffer_Send_AddedPeriodic[iPoint];
14673 #endif
14674 
14675  /*--- Search all send/recv boundaries on this partition for halo cells. In
14676  particular, consider only the recv conditions (these are the true halo
14677  nodes). Check the ranks of the processors that are communicating and
14678  choose to keep only the halo cells from the higher rank processor. Here,
14679  we are also choosing to keep periodic nodes that were part of the original
14680  domain. We will check the communicated list of added periodic points. ---*/
14681 
14682  Local_Halo = new int[geometry->GetnPoint()];
14683  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
14684  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
14685 
14686  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
14687  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
14688  SendRecv = config->GetMarker_All_SendRecv(iMarker);
14689  RecvFrom = abs(SendRecv)-1;
14690 
14691  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
14692  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
14693  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
14694 
14695  /*--- We need to keep one copy of overlapping halo cells. ---*/
14696 
14697  notHalo = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() == 0) &&
14698  (SendRecv < 0) && (rank > RecvFrom));
14699 
14700  /*--- We want to keep the periodic nodes that were part of the original domain.
14701  For SU2_DEF we want to keep all periodic nodes. ---*/
14702 
14703  if (config->GetKind_SU2() == SU2_DEF) {
14704  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0));
14705  }else {
14706  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
14707  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
14708  }
14709 
14710  notPeriodic = (isPeriodic && (SendRecv < 0));
14711 
14712  /*--- Lastly, check that this isn't an added periodic point that
14713  we will forcibly remove. Use the communicated list of these points. ---*/
14714 
14715  addedPeriodic = false; kPoint = 0;
14716  for (iProcessor = 0; iProcessor < (unsigned long)size; iProcessor++) {
14717  for (jPoint = 0; jPoint < Buffer_Recv_nAddedPeriodic[iProcessor]; jPoint++) {
14718  if (Global_Index == Buffer_Recv_AddedPeriodic[kPoint+jPoint])
14719  addedPeriodic = true;
14720  }
14721 
14722  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
14723 
14724  kPoint = (iProcessor+1)*maxAddedPeriodic;
14725 
14726  }
14727 
14728  /*--- If we found either of these types of nodes, flag them to be kept. ---*/
14729 
14730  if ((notHalo || notPeriodic) && !addedPeriodic) {
14731  Local_Halo[iPoint] = false;
14732  }
14733 
14734  }
14735  }
14736  }
14737 
14738  /*--- Now that we've done the gymnastics to find any periodic points,
14739  compute the total number of local and global points for the output. ---*/
14740 
14741  nLocalPoint = 0;
14742  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
14743  if (Local_Halo[iPoint] == false)
14744  nLocalPoint++;
14745 
14746 #ifdef HAVE_MPI
14747  SU2_MPI::Allreduce(&nLocalPoint, &nTotalPoint, 1,
14749 #else
14750  nTotalPoint = nLocalPoint;
14751 #endif
14752 
14753  /*--- Compute the number of points that will be on each processor.
14754  This is a linear partitioning with the addition of a simple load
14755  balancing for any remainder points. ---*/
14756 
14757  unsigned long *npoint_procs = new unsigned long[size];
14758  unsigned long *starting_node = new unsigned long[size];
14759  unsigned long *ending_node = new unsigned long[size];
14760  unsigned long *nPoint_Linear = new unsigned long[size+1];
14761 
14762  unsigned long total_pt_accounted = 0;
14763  for (int ii = 0; ii < size; ii++) {
14764  npoint_procs[ii] = nTotalPoint/size;
14765  total_pt_accounted = total_pt_accounted + npoint_procs[ii];
14766  }
14767 
14768  /*--- Get the number of remainder points after the even division. ---*/
14769 
14770  unsigned long rem_points = nTotalPoint-total_pt_accounted;
14771  for (unsigned long ii = 0; ii < rem_points; ii++) {
14772  npoint_procs[ii]++;
14773  }
14774 
14775  /*--- Store the local number of nodes and the beginning/end index ---*/
14776 
14777  starting_node[0] = 0;
14778  ending_node[0] = starting_node[0] + npoint_procs[0];
14779  nPoint_Linear[0] = 0;
14780  for (int ii = 1; ii < size; ii++) {
14781  starting_node[ii] = ending_node[ii-1];
14782  ending_node[ii] = starting_node[ii] + npoint_procs[ii];
14783  nPoint_Linear[ii] = nPoint_Linear[ii-1] + npoint_procs[ii-1];
14784  }
14785  nPoint_Linear[size] = nTotalPoint;
14786 
14787  /*--- We start with the connectivity distributed across all procs with
14788  no particular ordering assumed. We need to loop through our local partition
14789  and decide how many elements we must send to each other rank in order to
14790  have all elements sorted according to a linear partitioning of the grid
14791  nodes, i.e., rank 0 holds the first nPoint()/nProcessors nodes.
14792  First, initialize a counter and flag. ---*/
14793 
14794  int *nElem_Send = new int[size+1]; nElem_Send[0] = 0;
14795  int *nElem_Recv = new int[size+1]; nElem_Recv[0] = 0;
14796  int *nElem_Flag = new int[size];
14797 
14798  for (int ii=0; ii < size; ii++) {
14799  nElem_Send[ii] = 0;
14800  nElem_Recv[ii] = 0;
14801  nElem_Flag[ii]= -1;
14802  }
14803  nElem_Send[size] = 0; nElem_Recv[size] = 0;
14804 
14805  for (int ii = 0; ii < (int)geometry->GetnElem(); ii++ ) {
14806  if (geometry->elem[ii]->GetVTK_Type() == Elem_Type) {
14807  for ( int jj = 0; jj < NODES_PER_ELEMENT; jj++ ) {
14808 
14809  /*--- Get the index of the current point. ---*/
14810 
14811  iPoint = geometry->elem[ii]->GetNode(jj);
14812  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
14813 
14814  /*--- Search for the lowest global index in this element. We
14815  send the element to the processor owning the range that includes
14816  the lowest global index value. ---*/
14817 
14818  for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) {
14819  jPoint = geometry->elem[ii]->GetNode(kk);
14820  unsigned long newID = geometry->node[jPoint]->GetGlobalIndex();
14821  if (newID < Global_Index) Global_Index = newID;
14822  }
14823 
14824  /*--- Search for the processor that owns this point ---*/
14825 
14826  iProcessor = Global_Index/npoint_procs[0];
14827  if (iProcessor >= (unsigned long)size)
14828  iProcessor = (unsigned long)size-1;
14829  if (Global_Index >= nPoint_Linear[iProcessor])
14830  while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++;
14831  else
14832  while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--;
14833 
14834  /*--- If we have not visited this element yet, increment our
14835  number of elements that must be sent to a particular proc. ---*/
14836 
14837  if ((nElem_Flag[iProcessor] != ii)) {
14838  nElem_Flag[iProcessor] = ii;
14839  nElem_Send[iProcessor+1]++;
14840  }
14841 
14842  }
14843  }
14844  }
14845 
14846  /*--- Communicate the number of cells to be sent/recv'd amongst
14847  all processors. After this communication, each proc knows how
14848  many cells it will receive from each other processor. ---*/
14849 
14850 #ifdef HAVE_MPI
14851  SU2_MPI::Alltoall(&(nElem_Send[1]), 1, MPI_INT,
14852  &(nElem_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD);
14853 #else
14854  nElem_Recv[1] = nElem_Send[1];
14855 #endif
14856 
14857  /*--- Prepare to send connectivities. First check how many
14858  messages we will be sending and receiving. Here we also put
14859  the counters into cumulative storage format to make the
14860  communications simpler. ---*/
14861 
14862  int nSends = 0, nRecvs = 0;
14863  for (int ii=0; ii < size; ii++) nElem_Flag[ii] = -1;
14864 
14865  for (int ii = 0; ii < size; ii++) {
14866  if ((ii != rank) && (nElem_Send[ii+1] > 0)) nSends++;
14867  if ((ii != rank) && (nElem_Recv[ii+1] > 0)) nRecvs++;
14868 
14869  nElem_Send[ii+1] += nElem_Send[ii];
14870  nElem_Recv[ii+1] += nElem_Recv[ii];
14871  }
14872 
14873  /*--- Allocate memory to hold the connectivity that we are
14874  sending. ---*/
14875 
14876  unsigned long *connSend = NULL;
14877  connSend = new unsigned long[NODES_PER_ELEMENT*nElem_Send[size]];
14878  for (int ii = 0; ii < NODES_PER_ELEMENT*nElem_Send[size]; ii++)
14879  connSend[ii] = 0;
14880 
14881  /*--- Allocate arrays for storing halo flags. ---*/
14882 
14883  unsigned short *haloSend = new unsigned short[nElem_Send[size]];
14884  for (int ii = 0; ii < nElem_Send[size]; ii++)
14885  haloSend[ii] = false;
14886 
14887  /*--- Create an index variable to keep track of our index
14888  position as we load up the send buffer. ---*/
14889 
14890  unsigned long *index = new unsigned long[size];
14891  for (int ii=0; ii < size; ii++) index[ii] = NODES_PER_ELEMENT*nElem_Send[ii];
14892 
14893  unsigned long *haloIndex = new unsigned long[size];
14894  for (int ii=0; ii < size; ii++) haloIndex[ii] = nElem_Send[ii];
14895 
14896  /*--- Loop through our elements and load the elems and their
14897  additional data that we will send to the other procs. ---*/
14898 
14899  for (int ii = 0; ii < (int)geometry->GetnElem(); ii++) {
14900  if (geometry->elem[ii]->GetVTK_Type() == Elem_Type) {
14901  for ( int jj = 0; jj < NODES_PER_ELEMENT; jj++ ) {
14902 
14903  /*--- Get the index of the current point. ---*/
14904 
14905  iPoint = geometry->elem[ii]->GetNode(jj);
14906  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
14907 
14908  /*--- Search for the lowest global index in this element. We
14909  send the element to the processor owning the range that includes
14910  the lowest global index value. ---*/
14911 
14912  for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) {
14913  jPoint = geometry->elem[ii]->GetNode(kk);
14914  unsigned long newID = geometry->node[jPoint]->GetGlobalIndex();
14915  if (newID < Global_Index) Global_Index = newID;
14916  }
14917 
14918  /*--- Search for the processor that owns this point ---*/
14919 
14920  iProcessor = Global_Index/npoint_procs[0];
14921  if (iProcessor >= (unsigned long)size)
14922  iProcessor = (unsigned long)size-1;
14923  if (Global_Index >= nPoint_Linear[iProcessor])
14924  while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++;
14925  else
14926  while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--;
14927 
14928  /*--- Load connectivity into the buffer for sending ---*/
14929 
14930  if (nElem_Flag[iProcessor] != ii) {
14931 
14932  nElem_Flag[iProcessor] = ii;
14933  unsigned long nn = index[iProcessor];
14934  unsigned long mm = haloIndex[iProcessor];
14935 
14936  /*--- Load the connectivity values. ---*/
14937 
14938  for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) {
14939  iPoint = geometry->elem[ii]->GetNode(kk);
14940  connSend[nn] = geometry->node[iPoint]->GetGlobalIndex(); nn++;
14941 
14942  /*--- Check if this is a halo node. If so, flag this element
14943  as a halo cell. We will use this later to sort and remove
14944  any duplicates from the connectivity list. ---*/
14945 
14946  if (Local_Halo[iPoint]) haloSend[mm] = true;
14947 
14948  }
14949 
14950  /*--- Increment the index by the message length ---*/
14951 
14952  index[iProcessor] += NODES_PER_ELEMENT;
14953  haloIndex[iProcessor]++;
14954 
14955  }
14956  }
14957  }
14958  }
14959 
14960  /*--- Free memory after loading up the send buffer. ---*/
14961 
14962  delete [] index;
14963  delete [] haloIndex;
14964 
14965  /*--- Allocate the memory that we need for receiving the conn
14966  values and then cue up the non-blocking receives. Note that
14967  we do not include our own rank in the communications. We will
14968  directly copy our own data later. ---*/
14969 
14970  unsigned long *connRecv = NULL;
14971  connRecv = new unsigned long[NODES_PER_ELEMENT*nElem_Recv[size]];
14972  for (int ii = 0; ii < NODES_PER_ELEMENT*nElem_Recv[size]; ii++)
14973  connRecv[ii] = 0;
14974 
14975  unsigned short *haloRecv = new unsigned short[nElem_Recv[size]];
14976  for (int ii = 0; ii < nElem_Recv[size]; ii++)
14977  haloRecv[ii] = false;
14978 
14979 #ifdef HAVE_MPI
14980  /*--- We need double the number of messages to send both the conn.
14981  and the flags for the halo cells. ---*/
14982 
14983  send_req = new SU2_MPI::Request[2*nSends];
14984  recv_req = new SU2_MPI::Request[2*nRecvs];
14985 
14986  /*--- Launch the non-blocking recv's for the connectivity. ---*/
14987 
14988  unsigned long iMessage = 0;
14989  for (int ii=0; ii<size; ii++) {
14990  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
14991  int ll = NODES_PER_ELEMENT*nElem_Recv[ii];
14992  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
14993  int count = NODES_PER_ELEMENT*kk;
14994  int source = ii;
14995  int tag = ii + 1;
14996  SU2_MPI::Irecv(&(connRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
14997  MPI_COMM_WORLD, &(recv_req[iMessage]));
14998  iMessage++;
14999  }
15000  }
15001 
15002  /*--- Launch the non-blocking sends of the connectivity. ---*/
15003 
15004  iMessage = 0;
15005  for (int ii=0; ii<size; ii++) {
15006  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
15007  int ll = NODES_PER_ELEMENT*nElem_Send[ii];
15008  int kk = nElem_Send[ii+1] - nElem_Send[ii];
15009  int count = NODES_PER_ELEMENT*kk;
15010  int dest = ii;
15011  int tag = rank + 1;
15012  SU2_MPI::Isend(&(connSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
15013  MPI_COMM_WORLD, &(send_req[iMessage]));
15014  iMessage++;
15015  }
15016  }
15017 
15018  /*--- Repeat the process to communicate the halo flags. ---*/
15019 
15020  iMessage = 0;
15021  for (int ii=0; ii<size; ii++) {
15022  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
15023  int ll = nElem_Recv[ii];
15024  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
15025  int count = kk;
15026  int source = ii;
15027  int tag = ii + 1;
15028  SU2_MPI::Irecv(&(haloRecv[ll]), count, MPI_UNSIGNED_SHORT, source, tag,
15029  MPI_COMM_WORLD, &(recv_req[iMessage+nRecvs]));
15030  iMessage++;
15031  }
15032  }
15033 
15034  /*--- Launch the non-blocking sends of the halo flags. ---*/
15035 
15036  iMessage = 0;
15037  for (int ii=0; ii<size; ii++) {
15038  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
15039  int ll = nElem_Send[ii];
15040  int kk = nElem_Send[ii+1] - nElem_Send[ii];
15041  int count = kk;
15042  int dest = ii;
15043  int tag = rank + 1;
15044  SU2_MPI::Isend(&(haloSend[ll]), count, MPI_UNSIGNED_SHORT, dest, tag,
15045  MPI_COMM_WORLD, &(send_req[iMessage+nSends]));
15046  iMessage++;
15047  }
15048  }
15049 #endif
15050 
15051  /*--- Copy my own rank's data into the recv buffer directly. ---*/
15052 
15053  int mm = NODES_PER_ELEMENT*nElem_Recv[rank];
15054  int ll = NODES_PER_ELEMENT*nElem_Send[rank];
15055  int kk = NODES_PER_ELEMENT*nElem_Send[rank+1];
15056 
15057  for (int nn=ll; nn<kk; nn++, mm++) connRecv[mm] = connSend[nn];
15058 
15059  mm = nElem_Recv[rank];
15060  ll = nElem_Send[rank];
15061  kk = nElem_Send[rank+1];
15062 
15063  for (int nn=ll; nn<kk; nn++, mm++) haloRecv[mm] = haloSend[nn];
15064 
15065  /*--- Wait for the non-blocking sends and recvs to complete. ---*/
15066 
15067 #ifdef HAVE_MPI
15068  int number = 2*nSends;
15069  for (int ii = 0; ii < number; ii++)
15070  SU2_MPI::Waitany(number, send_req, &ind, &status);
15071 
15072  number = 2*nRecvs;
15073  for (int ii = 0; ii < number; ii++)
15074  SU2_MPI::Waitany(number, recv_req, &ind, &status);
15075 
15076  delete [] send_req;
15077  delete [] recv_req;
15078 #endif
15079 
15080  /*--- Store the connectivity for this rank in the proper data
15081  structure before post-processing below. Note that we add 1 here
15082  to the connectivity for vizualization packages. First, allocate
15083  appropriate amount of memory for this section. ---*/
15084 
15085  if (nElem_Recv[size] > 0) Conn_Elem = new int[NODES_PER_ELEMENT*nElem_Recv[size]];
15086  int count = 0; nElem_Total = 0;
15087  for (int ii = 0; ii < nElem_Recv[size]; ii++) {
15088  if (!haloRecv[ii]) {
15089  nElem_Total++;
15090  for (int jj = 0; jj < NODES_PER_ELEMENT; jj++) {
15091  Conn_Elem[count] = (int)connRecv[ii*NODES_PER_ELEMENT+jj] + 1;
15092  count++;
15093  }
15094  }
15095  }
15096 
15097  /*--- Store the particular global element count in the class data,
15098  and set the class data pointer to the connectivity array. ---*/
15099 
15100  switch (Elem_Type) {
15101  case TRIANGLE:
15102  nParallel_Tria = nElem_Total;
15103  if (nParallel_Tria > 0) Conn_Tria_Par = Conn_Elem;
15104  break;
15105  case QUADRILATERAL:
15106  nParallel_Quad = nElem_Total;
15107  if (nParallel_Quad > 0) Conn_Quad_Par = Conn_Elem;
15108  break;
15109  case TETRAHEDRON:
15110  nParallel_Tetr = nElem_Total;
15111  if (nParallel_Tetr > 0) Conn_Tetr_Par = Conn_Elem;
15112  break;
15113  case HEXAHEDRON:
15114  nParallel_Hexa = nElem_Total;
15115  if (nParallel_Hexa > 0) Conn_Hexa_Par = Conn_Elem;
15116  break;
15117  case PRISM:
15118  nParallel_Pris = nElem_Total;
15119  if (nParallel_Pris > 0) Conn_Pris_Par = Conn_Elem;
15120  break;
15121  case PYRAMID:
15122  nParallel_Pyra = nElem_Total;
15123  if (nParallel_Pyra > 0) Conn_Pyra_Par = Conn_Elem;
15124  break;
15125  default:
15126  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
15127  break;
15128  }
15129 
15130  /*--- Free temporary memory from communications ---*/
15131 
15132  delete [] connSend;
15133  delete [] connRecv;
15134  delete [] haloSend;
15135  delete [] haloRecv;
15136  delete [] Local_Halo;
15137  delete [] nElem_Recv;
15138  delete [] nElem_Send;
15139  delete [] nElem_Flag;
15140  delete [] Buffer_Recv_nAddedPeriodic;
15141  delete [] Buffer_Send_AddedPeriodic;
15142  delete [] Buffer_Recv_AddedPeriodic;
15143  delete [] npoint_procs;
15144  delete [] starting_node;
15145  delete [] ending_node;
15146  delete [] nPoint_Linear;
15147 
15148 }
15149 
15150 void COutput::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) {
15151 
15152  unsigned long iProcessor;
15153  unsigned short NODES_PER_ELEMENT;
15154  unsigned long iPoint, jPoint, kPoint, nLocalPoint, nTotalPoint;
15155  unsigned long nElem_Total = 0, Global_Index;
15156 
15157  unsigned long iVertex, iMarker;
15158  int SendRecv, RecvFrom;
15159 
15160  bool notPeriodic, notHalo, addedPeriodic, isPeriodic;
15161 
15162  int *Local_Halo = NULL;
15163  int *Conn_Elem = NULL;
15164 
15165 #ifdef HAVE_MPI
15166  SU2_MPI::Request *send_req, *recv_req;
15167  SU2_MPI::Status status;
15168  int ind;
15169 #endif
15170 
15171  /*--- Store the local number of this element type and the number of nodes
15172  per this element type. In serial, this will be the total number of this
15173  element type in the entire mesh. In parallel, it is the number on only
15174  the current partition. ---*/
15175 
15176  switch (Elem_Type) {
15177  case LINE:
15178  NODES_PER_ELEMENT = N_POINTS_LINE;
15179  break;
15180  case TRIANGLE:
15181  NODES_PER_ELEMENT = N_POINTS_TRIANGLE;
15182  break;
15183  case QUADRILATERAL:
15184  NODES_PER_ELEMENT = N_POINTS_QUADRILATERAL;
15185  break;
15186  default:
15187  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
15188  NODES_PER_ELEMENT = 0;
15189  break;
15190  }
15191 
15192  /*--- Force the removal of all added periodic elements (use global index).
15193  First, we isolate and create a list of all added periodic points, excluding
15194  those that were part of the original domain (we want these to be in the
15195  output files). ---*/
15196 
15197  vector<unsigned long> Added_Periodic;
15198  Added_Periodic.clear();
15199 
15200  if (config->GetKind_SU2() != SU2_DEF) {
15201  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
15202  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
15203  SendRecv = config->GetMarker_All_SendRecv(iMarker);
15204  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
15205  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
15206 
15207  if ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
15208  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 0) &&
15209  (SendRecv < 0)) {
15210  Added_Periodic.push_back(geometry->node[iPoint]->GetGlobalIndex());
15211  }
15212  }
15213  }
15214  }
15215  }
15216 
15217  /*--- Now we communicate this information to all processors, so that they
15218  can force the removal of these particular nodes by flagging them as halo
15219  points. In general, this should be a small percentage of the total mesh,
15220  so the communication/storage costs here shouldn't be prohibitive. ---*/
15221 
15222  /*--- First communicate the number of points that each rank has found. ---*/
15223 
15224  unsigned long nAddedPeriodic = 0, maxAddedPeriodic = 0;
15225  unsigned long Buffer_Send_nAddedPeriodic[1], *Buffer_Recv_nAddedPeriodic = NULL;
15226  Buffer_Recv_nAddedPeriodic = new unsigned long[size];
15227 
15228  nAddedPeriodic = Added_Periodic.size();
15229  Buffer_Send_nAddedPeriodic[0] = nAddedPeriodic;
15230 
15231 #ifdef HAVE_MPI
15232  SU2_MPI::Allreduce(&nAddedPeriodic, &maxAddedPeriodic, 1, MPI_UNSIGNED_LONG,
15234  SU2_MPI::Allgather(&Buffer_Send_nAddedPeriodic, 1, MPI_UNSIGNED_LONG,
15235  Buffer_Recv_nAddedPeriodic, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
15236 #else
15237  maxAddedPeriodic = nAddedPeriodic;
15238  Buffer_Recv_nAddedPeriodic[0] = Buffer_Send_nAddedPeriodic[0];
15239 #endif
15240 
15241  /*--- Communicate the global index values of all added periodic nodes. ---*/
15242  unsigned long *Buffer_Send_AddedPeriodic = new unsigned long[maxAddedPeriodic];
15243  unsigned long *Buffer_Recv_AddedPeriodic = new unsigned long[size*maxAddedPeriodic];
15244 
15245  for (iPoint = 0; iPoint < Added_Periodic.size(); iPoint++) {
15246  Buffer_Send_AddedPeriodic[iPoint] = Added_Periodic[iPoint];
15247  }
15248 
15249  /*--- Gather the element connectivity information. All processors will now
15250  have a copy of the global index values for all added periodic points. ---*/
15251 
15252 #ifdef HAVE_MPI
15253  SU2_MPI::Allgather(Buffer_Send_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
15254  Buffer_Recv_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
15255  MPI_COMM_WORLD);
15256 #else
15257  for (iPoint = 0; iPoint < maxAddedPeriodic; iPoint++)
15258  Buffer_Recv_AddedPeriodic[iPoint] = Buffer_Send_AddedPeriodic[iPoint];
15259 #endif
15260 
15261  /*--- Search all send/recv boundaries on this partition for halo cells. In
15262  particular, consider only the recv conditions (these are the true halo
15263  nodes). Check the ranks of the processors that are communicating and
15264  choose to keep only the halo cells from the higher rank processor. Here,
15265  we are also choosing to keep periodic nodes that were part of the original
15266  domain. We will check the communicated list of added periodic points. ---*/
15267 
15268  Local_Halo = new int[geometry->GetnPoint()];
15269  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
15270  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
15271 
15272  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
15273  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
15274  SendRecv = config->GetMarker_All_SendRecv(iMarker);
15275  RecvFrom = abs(SendRecv)-1;
15276 
15277  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
15278  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
15279  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
15280 
15281  /*--- We need to keep one copy of overlapping halo cells. ---*/
15282 
15283  notHalo = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() == 0) &&
15284  (SendRecv < 0) && (rank > RecvFrom));
15285 
15286  /*--- We want to keep the periodic nodes that were part of the original domain.
15287  For SU2_DEF we want to keep all periodic nodes. ---*/
15288 
15289  if (config->GetKind_SU2() == SU2_DEF) {
15290  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0));
15291  }else {
15292  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
15293  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
15294  }
15295 
15296  notPeriodic = (isPeriodic && (SendRecv < 0));
15297 
15298  /*--- Lastly, check that this isn't an added periodic point that
15299  we will forcibly remove. Use the communicated list of these points. ---*/
15300 
15301  addedPeriodic = false; kPoint = 0;
15302  for (iProcessor = 0; iProcessor < (unsigned long)size; iProcessor++) {
15303  for (jPoint = 0; jPoint < Buffer_Recv_nAddedPeriodic[iProcessor]; jPoint++) {
15304  if (Global_Index == Buffer_Recv_AddedPeriodic[kPoint+jPoint])
15305  addedPeriodic = true;
15306  }
15307 
15308  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
15309 
15310  kPoint = (iProcessor+1)*maxAddedPeriodic;
15311 
15312  }
15313 
15314  /*--- If we found either of these types of nodes, flag them to be kept. ---*/
15315 
15316  if ((notHalo || notPeriodic) && !addedPeriodic) {
15317  Local_Halo[iPoint] = false;
15318  }
15319 
15320  }
15321  }
15322  }
15323 
15324  /*--- Now that we've done the gymnastics to find any periodic points,
15325  compute the total number of local and global points for the output. ---*/
15326 
15327  nLocalPoint = 0;
15328  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
15329  if (Local_Halo[iPoint] == false)
15330  nLocalPoint++;
15331 
15332 #ifdef HAVE_MPI
15333  SU2_MPI::Allreduce(&nLocalPoint, &nTotalPoint, 1,
15335 #else
15336  nTotalPoint = nLocalPoint;
15337 #endif
15338 
15339  /*--- Compute the number of points that will be on each processor.
15340  This is a linear partitioning with the addition of a simple load
15341  balancing for any remainder points. ---*/
15342 
15343  unsigned long *npoint_procs = new unsigned long[size];
15344  unsigned long *starting_node = new unsigned long[size];
15345  unsigned long *ending_node = new unsigned long[size];
15346  unsigned long *nPoint_Linear = new unsigned long[size+1];
15347 
15348  unsigned long total_pt_accounted = 0;
15349  for (int ii = 0; ii < size; ii++) {
15350  npoint_procs[ii] = nTotalPoint/size;
15351  total_pt_accounted = total_pt_accounted + npoint_procs[ii];
15352  }
15353 
15354  /*--- Get the number of remainder points after the even division. ---*/
15355 
15356  unsigned long rem_points = nTotalPoint-total_pt_accounted;
15357  for (unsigned long ii = 0; ii < rem_points; ii++) {
15358  npoint_procs[ii]++;
15359  }
15360 
15361  /*--- Store the local number of nodes and the beginning/end index ---*/
15362 
15363  starting_node[0] = 0;
15364  ending_node[0] = starting_node[0] + npoint_procs[0];
15365  nPoint_Linear[0] = 0;
15366  for (int ii = 1; ii < size; ii++) {
15367  starting_node[ii] = ending_node[ii-1];
15368  ending_node[ii] = starting_node[ii] + npoint_procs[ii];
15369  nPoint_Linear[ii] = nPoint_Linear[ii-1] + npoint_procs[ii-1];
15370  }
15371  nPoint_Linear[size] = nTotalPoint;
15372 
15373  /*--- We start with the connectivity distributed across all procs with
15374  no particular ordering assumed. We need to loop through our local partition
15375  and decide how many elements we must send to each other rank in order to
15376  have all elements sorted according to a linear partitioning of the grid
15377  nodes, i.e., rank 0 holds the first nPoint()/nProcessors nodes.
15378  First, initialize a counter and flag. ---*/
15379 
15380  int *nElem_Send = new int[size+1]; nElem_Send[0] = 0;
15381  int *nElem_Recv = new int[size+1]; nElem_Recv[0] = 0;
15382  int *nElem_Flag = new int[size];
15383 
15384  for (int ii=0; ii < size; ii++) {
15385  nElem_Send[ii] = 0;
15386  nElem_Recv[ii] = 0;
15387  nElem_Flag[ii]= -1;
15388  }
15389  nElem_Send[size] = 0; nElem_Recv[size] = 0;
15390 
15391  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
15392  if (config->GetMarker_All_Plotting(iMarker) == YES) {
15393 
15394  for (int ii = 0; ii < (int)geometry->GetnElem_Bound(iMarker); ii++) {
15395 
15396  if (geometry->bound[iMarker][ii]->GetVTK_Type() == Elem_Type) {
15397  for ( int jj = 0; jj < NODES_PER_ELEMENT; jj++ ) {
15398 
15399  /*--- Get the index of the current point. ---*/
15400 
15401  iPoint = geometry->bound[iMarker][ii]->GetNode(jj);
15402  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
15403 
15404  /*--- Search for the lowest global index in this element. We
15405  send the element to the processor owning the range that includes
15406  the lowest global index value. ---*/
15407 
15408  for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) {
15409  jPoint = geometry->bound[iMarker][ii]->GetNode(kk);
15410  unsigned long newID = geometry->node[jPoint]->GetGlobalIndex();
15411  if (newID < Global_Index) Global_Index = newID;
15412  }
15413 
15414  /*--- Search for the processor that owns this point ---*/
15415 
15416  iProcessor = Global_Index/npoint_procs[0];
15417  if (iProcessor >= (unsigned long)size)
15418  iProcessor = (unsigned long)size-1;
15419  if (Global_Index >= nPoint_Linear[iProcessor])
15420  while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++;
15421  else
15422  while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--;
15423 
15424  /*--- If we have not visited this element yet, increment our
15425  number of elements that must be sent to a particular proc. ---*/
15426 
15427  if ((nElem_Flag[iProcessor] != ii)) {
15428  nElem_Flag[iProcessor] = ii;
15429  nElem_Send[iProcessor+1]++;
15430  }
15431 
15432  }
15433  }
15434  }
15435  }
15436  }
15437 
15438  /*--- Communicate the number of cells to be sent/recv'd amongst
15439  all processors. After this communication, each proc knows how
15440  many cells it will receive from each other processor. ---*/
15441 
15442 #ifdef HAVE_MPI
15443  SU2_MPI::Alltoall(&(nElem_Send[1]), 1, MPI_INT,
15444  &(nElem_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD);
15445 #else
15446  nElem_Recv[1] = nElem_Send[1];
15447 #endif
15448 
15449  /*--- Prepare to send connectivities. First check how many
15450  messages we will be sending and receiving. Here we also put
15451  the counters into cumulative storage format to make the
15452  communications simpler. ---*/
15453 
15454  int nSends = 0, nRecvs = 0;
15455  for (int ii=0; ii < size; ii++) nElem_Flag[ii] = -1;
15456 
15457  for (int ii = 0; ii < size; ii++) {
15458  if ((ii != rank) && (nElem_Send[ii+1] > 0)) nSends++;
15459  if ((ii != rank) && (nElem_Recv[ii+1] > 0)) nRecvs++;
15460 
15461  nElem_Send[ii+1] += nElem_Send[ii];
15462  nElem_Recv[ii+1] += nElem_Recv[ii];
15463  }
15464 
15465  /*--- Allocate memory to hold the connectivity that we are
15466  sending. ---*/
15467 
15468  unsigned long *connSend = NULL;
15469  connSend = new unsigned long[NODES_PER_ELEMENT*nElem_Send[size]];
15470  for (int ii = 0; ii < NODES_PER_ELEMENT*nElem_Send[size]; ii++)
15471  connSend[ii] = 0;
15472 
15473  /*--- Allocate arrays for storing halo flags. ---*/
15474 
15475  unsigned short *haloSend = new unsigned short[nElem_Send[size]];
15476  for (int ii = 0; ii < nElem_Send[size]; ii++)
15477  haloSend[ii] = false;
15478 
15479  /*--- Create an index variable to keep track of our index
15480  position as we load up the send buffer. ---*/
15481 
15482  unsigned long *index = new unsigned long[size];
15483  for (int ii=0; ii < size; ii++) index[ii] = NODES_PER_ELEMENT*nElem_Send[ii];
15484 
15485  unsigned long *haloIndex = new unsigned long[size];
15486  for (int ii=0; ii < size; ii++) haloIndex[ii] = nElem_Send[ii];
15487 
15488  /*--- Loop through our elements and load the elems and their
15489  additional data that we will send to the other procs. ---*/
15490 
15491  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
15492  if (config->GetMarker_All_Plotting(iMarker) == YES) {
15493 
15494  for (int ii = 0; ii < (int)geometry->GetnElem_Bound(iMarker); ii++) {
15495 
15496  if (geometry->bound[iMarker][ii]->GetVTK_Type() == Elem_Type) {
15497  for ( int jj = 0; jj < NODES_PER_ELEMENT; jj++ ) {
15498 
15499  /*--- Get the index of the current point. ---*/
15500 
15501  iPoint = geometry->bound[iMarker][ii]->GetNode(jj);
15502  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
15503 
15504  /*--- Search for the lowest global index in this element. We
15505  send the element to the processor owning the range that includes
15506  the lowest global index value. ---*/
15507 
15508  for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) {
15509  jPoint = geometry->bound[iMarker][ii]->GetNode(kk);
15510  unsigned long newID = geometry->node[jPoint]->GetGlobalIndex();
15511  if (newID < Global_Index) Global_Index = newID;
15512  }
15513 
15514  /*--- Search for the processor that owns this point ---*/
15515 
15516  iProcessor = Global_Index/npoint_procs[0];
15517  if (iProcessor >= (unsigned long)size)
15518  iProcessor = (unsigned long)size-1;
15519  if (Global_Index >= nPoint_Linear[iProcessor])
15520  while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++;
15521  else
15522  while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--;
15523 
15524  /*--- Load connectivity into the buffer for sending ---*/
15525 
15526  if (nElem_Flag[iProcessor] != ii) {
15527 
15528  nElem_Flag[iProcessor] = ii;
15529  unsigned long nn = index[iProcessor];
15530  unsigned long mm = haloIndex[iProcessor];
15531 
15532  /*--- Load the connectivity values. ---*/
15533 
15534  for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) {
15535  iPoint = geometry->bound[iMarker][ii]->GetNode(kk);
15536  connSend[nn] = geometry->node[iPoint]->GetGlobalIndex(); nn++;
15537 
15538  /*--- Check if this is a halo node. If so, flag this element
15539  as a halo cell. We will use this later to sort and remove
15540  any duplicates from the connectivity list. ---*/
15541 
15542  if (Local_Halo[iPoint]) haloSend[mm] = true;
15543 
15544  }
15545 
15546  /*--- Increment the index by the message length ---*/
15547 
15548  index[iProcessor] += NODES_PER_ELEMENT;
15549  haloIndex[iProcessor]++;
15550 
15551  }
15552  }
15553  }
15554  }
15555  }
15556  }
15557 
15558  /*--- Free memory after loading up the send buffer. ---*/
15559 
15560  delete [] index;
15561  delete [] haloIndex;
15562 
15563  /*--- Allocate the memory that we need for receiving the conn
15564  values and then cue up the non-blocking receives. Note that
15565  we do not include our own rank in the communications. We will
15566  directly copy our own data later. ---*/
15567 
15568  unsigned long *connRecv = NULL;
15569  connRecv = new unsigned long[NODES_PER_ELEMENT*nElem_Recv[size]];
15570  for (int ii = 0; ii < NODES_PER_ELEMENT*nElem_Recv[size]; ii++)
15571  connRecv[ii] = 0;
15572 
15573  unsigned short *haloRecv = new unsigned short[nElem_Recv[size]];
15574  for (int ii = 0; ii < nElem_Recv[size]; ii++)
15575  haloRecv[ii] = false;
15576 
15577 #ifdef HAVE_MPI
15578  /*--- We need double the number of messages to send both the conn.
15579  and the flags for the halo cells. ---*/
15580 
15581  send_req = new SU2_MPI::Request[2*nSends];
15582  recv_req = new SU2_MPI::Request[2*nRecvs];
15583 
15584  /*--- Launch the non-blocking recv's for the connectivity. ---*/
15585 
15586  unsigned long iMessage = 0;
15587  for (int ii=0; ii<size; ii++) {
15588  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
15589  int ll = NODES_PER_ELEMENT*nElem_Recv[ii];
15590  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
15591  int count = NODES_PER_ELEMENT*kk;
15592  int source = ii;
15593  int tag = ii + 1;
15594  SU2_MPI::Irecv(&(connRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
15595  MPI_COMM_WORLD, &(recv_req[iMessage]));
15596  iMessage++;
15597  }
15598  }
15599 
15600  /*--- Launch the non-blocking sends of the connectivity. ---*/
15601 
15602  iMessage = 0;
15603  for (int ii=0; ii<size; ii++) {
15604  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
15605  int ll = NODES_PER_ELEMENT*nElem_Send[ii];
15606  int kk = nElem_Send[ii+1] - nElem_Send[ii];
15607  int count = NODES_PER_ELEMENT*kk;
15608  int dest = ii;
15609  int tag = rank + 1;
15610  SU2_MPI::Isend(&(connSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
15611  MPI_COMM_WORLD, &(send_req[iMessage]));
15612  iMessage++;
15613  }
15614  }
15615 
15616  /*--- Repeat the process to communicate the halo flags. ---*/
15617 
15618  iMessage = 0;
15619  for (int ii=0; ii<size; ii++) {
15620  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
15621  int ll = nElem_Recv[ii];
15622  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
15623  int count = kk;
15624  int source = ii;
15625  int tag = ii + 1;
15626  SU2_MPI::Irecv(&(haloRecv[ll]), count, MPI_UNSIGNED_SHORT, source, tag,
15627  MPI_COMM_WORLD, &(recv_req[iMessage+nRecvs]));
15628  iMessage++;
15629  }
15630  }
15631 
15632  /*--- Launch the non-blocking sends of the halo flags. ---*/
15633 
15634  iMessage = 0;
15635  for (int ii=0; ii<size; ii++) {
15636  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
15637  int ll = nElem_Send[ii];
15638  int kk = nElem_Send[ii+1] - nElem_Send[ii];
15639  int count = kk;
15640  int dest = ii;
15641  int tag = rank + 1;
15642  SU2_MPI::Isend(&(haloSend[ll]), count, MPI_UNSIGNED_SHORT, dest, tag,
15643  MPI_COMM_WORLD, &(send_req[iMessage+nSends]));
15644  iMessage++;
15645  }
15646  }
15647 #endif
15648 
15649  /*--- Copy my own rank's data into the recv buffer directly. ---*/
15650 
15651  int mm = NODES_PER_ELEMENT*nElem_Recv[rank];
15652  int ll = NODES_PER_ELEMENT*nElem_Send[rank];
15653  int kk = NODES_PER_ELEMENT*nElem_Send[rank+1];
15654 
15655  for (int nn=ll; nn<kk; nn++, mm++) connRecv[mm] = connSend[nn];
15656 
15657  mm = nElem_Recv[rank];
15658  ll = nElem_Send[rank];
15659  kk = nElem_Send[rank+1];
15660 
15661  for (int nn=ll; nn<kk; nn++, mm++) haloRecv[mm] = haloSend[nn];
15662 
15663  /*--- Wait for the non-blocking sends and recvs to complete. ---*/
15664 
15665 #ifdef HAVE_MPI
15666  int number = 2*nSends;
15667  for (int ii = 0; ii < number; ii++)
15668  SU2_MPI::Waitany(number, send_req, &ind, &status);
15669 
15670  number = 2*nRecvs;
15671  for (int ii = 0; ii < number; ii++)
15672  SU2_MPI::Waitany(number, recv_req, &ind, &status);
15673 
15674  delete [] send_req;
15675  delete [] recv_req;
15676 #endif
15677 
15678  /*--- Store the connectivity for this rank in the proper data
15679  structure before post-processing below. Note that we add 1 here
15680  to the connectivity for vizualization packages. First, allocate
15681  appropriate amount of memory for this section. ---*/
15682 
15683  if (nElem_Recv[size] > 0) Conn_Elem = new int[NODES_PER_ELEMENT*nElem_Recv[size]];
15684  int count = 0; nElem_Total = 0;
15685  for (int ii = 0; ii < nElem_Recv[size]; ii++) {
15686  if (!haloRecv[ii]) {
15687  nElem_Total++;
15688  for (int jj = 0; jj < NODES_PER_ELEMENT; jj++) {
15689  Conn_Elem[count] = (int)connRecv[ii*NODES_PER_ELEMENT+jj] + 1;
15690  count++;
15691  }
15692  }
15693  }
15694 
15695  /*--- Store the particular global element count in the class data,
15696  and set the class data pointer to the connectivity array. ---*/
15697 
15698  switch (Elem_Type) {
15699  case LINE:
15700  nParallel_Line = nElem_Total;
15701  if (nParallel_Line > 0) Conn_BoundLine_Par = Conn_Elem;
15702  break;
15703  case TRIANGLE:
15704  nParallel_BoundTria = nElem_Total;
15705  if (nParallel_BoundTria > 0) Conn_BoundTria_Par = Conn_Elem;
15706  break;
15707  case QUADRILATERAL:
15708  nParallel_BoundQuad = nElem_Total;
15709  if (nParallel_BoundQuad > 0) Conn_BoundQuad_Par = Conn_Elem;
15710  break;
15711  default:
15712  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
15713  break;
15714  }
15715 
15716  /*--- Free temporary memory from communications ---*/
15717 
15718  delete [] connSend;
15719  delete [] connRecv;
15720  delete [] haloSend;
15721  delete [] haloRecv;
15722  delete [] Local_Halo;
15723  delete [] nElem_Recv;
15724  delete [] nElem_Send;
15725  delete [] nElem_Flag;
15726  delete [] Buffer_Recv_nAddedPeriodic;
15727  delete [] Buffer_Send_AddedPeriodic;
15728  delete [] Buffer_Recv_AddedPeriodic;
15729  delete [] npoint_procs;
15730  delete [] starting_node;
15731  delete [] ending_node;
15732  delete [] nPoint_Linear;
15733 
15734 }
15735 
15736 void COutput::SortOutputData(CConfig *config, CGeometry *geometry) {
15737 
15738  unsigned short iMarker;
15739  unsigned long iProcessor;
15740  unsigned long iPoint, Global_Index, nLocalPoint, nTotalPoint, iVertex;
15741 
15742  int VARS_PER_POINT = nVar_Par;
15743  int *Local_Halo = NULL;
15744 
15745  bool isPeriodic;
15746 
15747 #ifdef HAVE_MPI
15748  SU2_MPI::Request *send_req, *recv_req;
15749  SU2_MPI::Status status;
15750  int ind;
15751 #endif
15752 
15753  /*--- Search all send/recv boundaries on this partition for any periodic
15754  nodes that were part of the original domain. We want to recover these
15755  for visualization purposes. ---*/
15756 
15757  Local_Halo = new int[geometry->GetnPoint()];
15758  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
15759  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
15760 
15761  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
15762  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
15763 
15764  /*--- Checking for less than or equal to the rank, because there may
15765  be some periodic halo nodes that send info to the same rank. ---*/
15766 
15767  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
15768  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
15769  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
15770  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
15771  if (isPeriodic) Local_Halo[iPoint] = false;
15772  }
15773  }
15774  }
15775 
15776  /*--- Sum total number of nodes that belong to the domain ---*/
15777 
15778  nLocalPoint = 0;
15779  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
15780  if (Local_Halo[iPoint] == false)
15781  nLocalPoint++;
15782 
15783 #ifdef HAVE_MPI
15784  SU2_MPI::Allreduce(&nLocalPoint, &nTotalPoint, 1,
15786 #else
15787  nTotalPoint = nLocalPoint;
15788 #endif
15789 
15790  /*--- Now that we know the actual number of points we need to output,
15791  compute the number of points that will be on each processor.
15792  This is a linear partitioning with the addition of a simple load
15793  balancing for any remainder points. ---*/
15794 
15795  unsigned long *npoint_procs = new unsigned long[size];
15796  unsigned long *starting_node = new unsigned long[size];
15797  unsigned long *ending_node = new unsigned long[size];
15798  unsigned long *nPoint_Linear = new unsigned long[size+1];
15799 
15800  unsigned long total_pt_accounted = 0;
15801  for (int ii = 0; ii < size; ii++) {
15802  npoint_procs[ii] = nTotalPoint/size;
15803  total_pt_accounted = total_pt_accounted + npoint_procs[ii];
15804  }
15805 
15806  /*--- Get the number of remainder points after the even division. ---*/
15807 
15808  unsigned long rem_points = nTotalPoint-total_pt_accounted;
15809  for (unsigned long ii = 0; ii < rem_points; ii++) {
15810  npoint_procs[ii]++;
15811  }
15812 
15813  /*--- Store the local number of nodes and the beginning/end index ---*/
15814 
15815  starting_node[0] = 0;
15816  ending_node[0] = starting_node[0] + npoint_procs[0];
15817  nPoint_Linear[0] = 0;
15818  for (int ii = 1; ii < size; ii++) {
15819  starting_node[ii] = ending_node[ii-1];
15820  ending_node[ii] = starting_node[ii] + npoint_procs[ii];
15821  nPoint_Linear[ii] = nPoint_Linear[ii-1] + npoint_procs[ii-1];
15822  }
15823  nPoint_Linear[size] = nTotalPoint;
15824 
15825  /*--- We start with the grid nodes distributed across all procs with
15826  no particular ordering assumed. We need to loop through our local partition
15827  and decide how many nodes we must send to each other rank in order to
15828  have all nodes sorted according to a linear partitioning of the grid
15829  nodes, i.e., rank 0 holds the first ~ nGlobalPoint()/nProcessors nodes.
15830  First, initialize a counter and flag. ---*/
15831 
15832  int *nPoint_Send = new int[size+1]; nPoint_Send[0] = 0;
15833  int *nPoint_Recv = new int[size+1]; nPoint_Recv[0] = 0;
15834  int *nPoint_Flag = new int[size];
15835 
15836  for (int ii=0; ii < size; ii++) {
15837  nPoint_Send[ii] = 0;
15838  nPoint_Recv[ii] = 0;
15839  nPoint_Flag[ii]= -1;
15840  }
15841  nPoint_Send[size] = 0; nPoint_Recv[size] = 0;
15842 
15843  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++ ) {
15844 
15845  /*--- We only write interior points and recovered periodic points. ---*/
15846 
15847  if (!Local_Halo[iPoint]) {
15848 
15849  /*--- Get the global index of the current point. ---*/
15850 
15851  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
15852 
15853  /*--- Search for the processor that owns this point ---*/
15854 
15855  iProcessor = Global_Index/npoint_procs[0];
15856  if (iProcessor >= (unsigned long)size)
15857  iProcessor = (unsigned long)size-1;
15858  if (Global_Index >= nPoint_Linear[iProcessor])
15859  while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++;
15860  else
15861  while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--;
15862 
15863  /*--- If we have not visited this node yet, increment our
15864  number of elements that must be sent to a particular proc. ---*/
15865 
15866  if (nPoint_Flag[iProcessor] != (int)iPoint) {
15867  nPoint_Flag[iProcessor] = (int)iPoint;
15868  nPoint_Send[iProcessor+1]++;
15869  }
15870 
15871  }
15872  }
15873 
15874  /*--- Communicate the number of nodes to be sent/recv'd amongst
15875  all processors. After this communication, each proc knows how
15876  many cells it will receive from each other processor. ---*/
15877 
15878 #ifdef HAVE_MPI
15879  SU2_MPI::Alltoall(&(nPoint_Send[1]), 1, MPI_INT,
15880  &(nPoint_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD);
15881 #else
15882  nPoint_Recv[1] = nPoint_Send[1];
15883 #endif
15884 
15885  /*--- Prepare to send coordinates. First check how many
15886  messages we will be sending and receiving. Here we also put
15887  the counters into cumulative storage format to make the
15888  communications simpler. ---*/
15889 
15890  int nSends = 0, nRecvs = 0;
15891  for (int ii=0; ii < size; ii++) nPoint_Flag[ii] = -1;
15892 
15893  for (int ii = 0; ii < size; ii++) {
15894  if ((ii != rank) && (nPoint_Send[ii+1] > 0)) nSends++;
15895  if ((ii != rank) && (nPoint_Recv[ii+1] > 0)) nRecvs++;
15896 
15897  nPoint_Send[ii+1] += nPoint_Send[ii];
15898  nPoint_Recv[ii+1] += nPoint_Recv[ii];
15899  }
15900 
15901  /*--- Allocate memory to hold the connectivity that we are
15902  sending. ---*/
15903 
15904  su2double *connSend = NULL;
15905  connSend = new su2double[VARS_PER_POINT*nPoint_Send[size]];
15906  for (int ii = 0; ii < VARS_PER_POINT*nPoint_Send[size]; ii++)
15907  connSend[ii] = 0;
15908 
15909  /*--- Allocate arrays for sending the global ID. ---*/
15910 
15911  unsigned long *idSend = new unsigned long[nPoint_Send[size]];
15912  for (int ii = 0; ii < nPoint_Send[size]; ii++)
15913  idSend[ii] = 0;
15914 
15915  /*--- Create an index variable to keep track of our index
15916  positions as we load up the send buffer. ---*/
15917 
15918  unsigned long *index = new unsigned long[size];
15919  for (int ii=0; ii < size; ii++) index[ii] = VARS_PER_POINT*nPoint_Send[ii];
15920 
15921  unsigned long *idIndex = new unsigned long[size];
15922  for (int ii=0; ii < size; ii++) idIndex[ii] = nPoint_Send[ii];
15923 
15924  /*--- Loop through our elements and load the elems and their
15925  additional data that we will send to the other procs. ---*/
15926 
15927  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) {
15928 
15929  /*--- We only write interior points and recovered periodic points. ---*/
15930 
15931  if (!Local_Halo[iPoint]) {
15932 
15933  /*--- Get the index of the current point. ---*/
15934 
15935  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
15936 
15937  /*--- Search for the processor that owns this point. ---*/
15938 
15939  iProcessor = Global_Index/npoint_procs[0];
15940  if (iProcessor >= (unsigned long)size)
15941  iProcessor = (unsigned long)size-1;
15942  if (Global_Index >= nPoint_Linear[iProcessor])
15943  while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++;
15944  else
15945  while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--;
15946 
15947  /*--- Load node coordinates into the buffer for sending. ---*/
15948 
15949  if (nPoint_Flag[iProcessor] != (int)iPoint) {
15950 
15951  nPoint_Flag[iProcessor] = (int)iPoint;
15952  unsigned long nn = index[iProcessor];
15953 
15954  /*--- Load the data values. ---*/
15955 
15956  for (unsigned short kk = 0; kk < VARS_PER_POINT; kk++) {
15957  connSend[nn] = Local_Data[iPoint][kk]; nn++;
15958  }
15959 
15960  /*--- Load the global ID (minus offset) for sorting the
15961  points once they all reach the correct processor. ---*/
15962 
15963  nn = idIndex[iProcessor];
15964  idSend[nn] = Global_Index - starting_node[iProcessor];
15965 
15966  /*--- Increment the index by the message length ---*/
15967 
15968  index[iProcessor] += VARS_PER_POINT;
15969  idIndex[iProcessor]++;
15970 
15971  }
15972  }
15973  }
15974 
15975  /*--- Free memory after loading up the send buffer. ---*/
15976 
15977  delete [] index;
15978  delete [] idIndex;
15979 
15980  /*--- Allocate the memory that we need for receiving the conn
15981  values and then cue up the non-blocking receives. Note that
15982  we do not include our own rank in the communications. We will
15983  directly copy our own data later. ---*/
15984 
15985  su2double *connRecv = NULL;
15986  connRecv = new su2double[VARS_PER_POINT*nPoint_Recv[size]];
15987  for (int ii = 0; ii < VARS_PER_POINT*nPoint_Recv[size]; ii++)
15988  connRecv[ii] = 0;
15989 
15990  unsigned long *idRecv = new unsigned long[nPoint_Recv[size]];
15991  for (int ii = 0; ii < nPoint_Recv[size]; ii++)
15992  idRecv[ii] = 0;
15993 
15994 #ifdef HAVE_MPI
15995  /*--- We need double the number of messages to send both the conn.
15996  and the global IDs. ---*/
15997 
15998  send_req = new SU2_MPI::Request[2*nSends];
15999  recv_req = new SU2_MPI::Request[2*nRecvs];
16000 
16001  unsigned long iMessage = 0;
16002  for (int ii=0; ii<size; ii++) {
16003  if ((ii != rank) && (nPoint_Recv[ii+1] > nPoint_Recv[ii])) {
16004  int ll = VARS_PER_POINT*nPoint_Recv[ii];
16005  int kk = nPoint_Recv[ii+1] - nPoint_Recv[ii];
16006  int count = VARS_PER_POINT*kk;
16007  int source = ii;
16008  int tag = ii + 1;
16009  SU2_MPI::Irecv(&(connRecv[ll]), count, MPI_DOUBLE, source, tag,
16010  MPI_COMM_WORLD, &(recv_req[iMessage]));
16011  iMessage++;
16012  }
16013  }
16014 
16015  /*--- Launch the non-blocking sends of the connectivity. ---*/
16016 
16017  iMessage = 0;
16018  for (int ii=0; ii<size; ii++) {
16019  if ((ii != rank) && (nPoint_Send[ii+1] > nPoint_Send[ii])) {
16020  int ll = VARS_PER_POINT*nPoint_Send[ii];
16021  int kk = nPoint_Send[ii+1] - nPoint_Send[ii];
16022  int count = VARS_PER_POINT*kk;
16023  int dest = ii;
16024  int tag = rank + 1;
16025  SU2_MPI::Isend(&(connSend[ll]), count, MPI_DOUBLE, dest, tag,
16026  MPI_COMM_WORLD, &(send_req[iMessage]));
16027  iMessage++;
16028  }
16029  }
16030 
16031  /*--- Repeat the process to communicate the global IDs. ---*/
16032 
16033  iMessage = 0;
16034  for (int ii=0; ii<size; ii++) {
16035  if ((ii != rank) && (nPoint_Recv[ii+1] > nPoint_Recv[ii])) {
16036  int ll = nPoint_Recv[ii];
16037  int kk = nPoint_Recv[ii+1] - nPoint_Recv[ii];
16038  int count = kk;
16039  int source = ii;
16040  int tag = ii + 1;
16041  SU2_MPI::Irecv(&(idRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
16042  MPI_COMM_WORLD, &(recv_req[iMessage+nRecvs]));
16043  iMessage++;
16044  }
16045  }
16046 
16047  /*--- Launch the non-blocking sends of the global IDs. ---*/
16048 
16049  iMessage = 0;
16050  for (int ii=0; ii<size; ii++) {
16051  if ((ii != rank) && (nPoint_Send[ii+1] > nPoint_Send[ii])) {
16052  int ll = nPoint_Send[ii];
16053  int kk = nPoint_Send[ii+1] - nPoint_Send[ii];
16054  int count = kk;
16055  int dest = ii;
16056  int tag = rank + 1;
16057  SU2_MPI::Isend(&(idSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
16058  MPI_COMM_WORLD, &(send_req[iMessage+nSends]));
16059  iMessage++;
16060  }
16061  }
16062 #endif
16063 
16064  /*--- Copy my own rank's data into the recv buffer directly. ---*/
16065 
16066  int mm = VARS_PER_POINT*nPoint_Recv[rank];
16067  int ll = VARS_PER_POINT*nPoint_Send[rank];
16068  int kk = VARS_PER_POINT*nPoint_Send[rank+1];
16069 
16070  for (int nn=ll; nn<kk; nn++, mm++) connRecv[mm] = connSend[nn];
16071 
16072  mm = nPoint_Recv[rank];
16073  ll = nPoint_Send[rank];
16074  kk = nPoint_Send[rank+1];
16075 
16076  for (int nn=ll; nn<kk; nn++, mm++) idRecv[mm] = idSend[nn];
16077 
16078  /*--- Wait for the non-blocking sends and recvs to complete. ---*/
16079 
16080 #ifdef HAVE_MPI
16081  int number = 2*nSends;
16082  for (int ii = 0; ii < number; ii++)
16083  SU2_MPI::Waitany(number, send_req, &ind, &status);
16084 
16085  number = 2*nRecvs;
16086  for (int ii = 0; ii < number; ii++)
16087  SU2_MPI::Waitany(number, recv_req, &ind, &status);
16088 
16089  delete [] send_req;
16090  delete [] recv_req;
16091 #endif
16092 
16093  /*--- Store the connectivity for this rank in the proper data
16094  structure before post-processing below. First, allocate the
16095  appropriate amount of memory for this section. ---*/
16096 
16097  Parallel_Data = new su2double*[VARS_PER_POINT];
16098  for (int jj = 0; jj < VARS_PER_POINT; jj++) {
16099  Parallel_Data[jj] = new su2double[nPoint_Recv[size]];
16100  for (int ii = 0; ii < nPoint_Recv[size]; ii++) {
16101  Parallel_Data[jj][idRecv[ii]] = connRecv[ii*VARS_PER_POINT+jj];
16102  }
16103  }
16104 
16105  /*--- Store the total number of local points my rank has for
16106  the current section after completing the communications. ---*/
16107 
16108  nParallel_Poin = nPoint_Recv[size];
16109 
16110  /*--- Reduce the total number of points we will write in the output files. ---*/
16111 
16112 #ifndef HAVE_MPI
16113  nGlobal_Poin_Par = nParallel_Poin;
16114 #else
16115  SU2_MPI::Allreduce(&nParallel_Poin, &nGlobal_Poin_Par, 1,
16117 #endif
16118 
16119  /*--- Free temporary memory from communications ---*/
16120 
16121  delete [] connSend;
16122  delete [] connRecv;
16123  delete [] idSend;
16124  delete [] idRecv;
16125  delete [] nPoint_Recv;
16126  delete [] nPoint_Send;
16127  delete [] nPoint_Flag;
16128 
16129  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
16130  delete [] Local_Data[iPoint];
16131  delete [] Local_Data;
16132 
16133  delete [] Local_Halo;
16134  delete [] npoint_procs;
16135  delete [] starting_node;
16136  delete [] ending_node;
16137  delete [] nPoint_Linear;
16138 
16139 }
16140 
16142 
16143  unsigned short iMarker;
16144  unsigned long iProcessor;
16145  unsigned long iPoint, jPoint, kPoint, iElem;
16146  unsigned long Global_Index, nLocalPoint, nTotalPoint, iVertex;
16147 
16148  int VARS_PER_POINT = nVar_Par;
16149  int *Local_Halo = NULL;
16150  int iNode, count;
16151  int SendRecv, RecvFrom;
16152 
16153  bool notPeriodic, notHalo, addedPeriodic, isPeriodic;
16154 
16155 #ifdef HAVE_MPI
16156  SU2_MPI::Request *send_req, *recv_req;
16157  SU2_MPI::Status status;
16158  int ind;
16159 #endif
16160 
16161  /*--------------------------------------------------------------------------*/
16162  /*--- Step 1: We already have the surface connectivity spread out in ---*/
16163  /*--- linear partitions across all procs and the output data ---*/
16164  /*--- for the entire field is similarly linearly partitioned. ---*/
16165  /*--- We need to identify which nodes in the volume data are ---*/
16166  /*--- also surface points. Our first step is to loop over all ---*/
16167  /*--- of the sorted surface connectivity and create a data ---*/
16168  /*--- structure on each proc that can identify the local surf ---*/
16169  /*--- points. Note that the linear partitioning is slightly ---*/
16170  /*--- different between the nodes and elements, so we will ---*/
16171  /*--- have to move between the two systems in this routine. ---*/
16172  /*--------------------------------------------------------------------------*/
16173 
16174  /*--- Search all send/recv boundaries on this partition for any periodic
16175  nodes that were part of the original domain. We want to recover these
16176  for visualization purposes. This is the linear partitioning for nodes. ---*/
16177 
16178  Local_Halo = new int[geometry->GetnPoint()];
16179  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
16180  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
16181 
16182  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
16183  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
16184 
16185  /*--- Checking for less than or equal to the rank, because there may
16186  be some periodic halo nodes that send info to the same rank. ---*/
16187 
16188  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
16189  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
16190  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
16191  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
16192  if (isPeriodic) Local_Halo[iPoint] = false;
16193  }
16194  }
16195  }
16196 
16197  /*--- Sum total number of nodes that belong to the domain ---*/
16198 
16199  nLocalPoint = 0;
16200  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
16201  if (Local_Halo[iPoint] == false)
16202  nLocalPoint++;
16203 
16204 #ifdef HAVE_MPI
16205  SU2_MPI::Allreduce(&nLocalPoint, &nTotalPoint, 1,
16207 #else
16208  nTotalPoint = nLocalPoint;
16209 #endif
16210 
16211  /*--- Now that we know the actual number of points we need to output,
16212  compute the number of points that will be on each processor.
16213  This is a linear partitioning with the addition of a simple load
16214  balancing for any remainder points. ---*/
16215 
16216  unsigned long *npoint_procs = new unsigned long[size];
16217  unsigned long *starting_node = new unsigned long[size];
16218  unsigned long *ending_node = new unsigned long[size];
16219 
16220  unsigned long *nPoint_Linear_Nodes = new unsigned long[size+1];
16221  unsigned long *nPoint_Linear_Elems = new unsigned long[size+1];
16222 
16223  unsigned long total_pt_accounted = 0;
16224  for (int ii = 0; ii < size; ii++) {
16225  npoint_procs[ii] = nTotalPoint/size;
16226  total_pt_accounted = total_pt_accounted + npoint_procs[ii];
16227  }
16228 
16229  /*--- Get the number of remainder points after the even division. ---*/
16230 
16231  unsigned long rem_points = nTotalPoint-total_pt_accounted;
16232  for (unsigned long ii = 0; ii < rem_points; ii++) {
16233  npoint_procs[ii]++;
16234  }
16235 
16236  /*--- Store the local number of nodes and the beginning/end index ---*/
16237 
16238  starting_node[0] = 0;
16239  ending_node[0] = starting_node[0] + npoint_procs[0];
16240  nPoint_Linear_Nodes[0] = 0;
16241  for (int ii = 1; ii < size; ii++) {
16242  starting_node[ii] = ending_node[ii-1];
16243  ending_node[ii] = starting_node[ii] + npoint_procs[ii];
16244  nPoint_Linear_Nodes[ii] = nPoint_Linear_Nodes[ii-1] + npoint_procs[ii-1];
16245  }
16246  nPoint_Linear_Nodes[size] = nTotalPoint;
16247 
16248  /*--- Prepare to check and communicate the nodes that each proc has
16249  locally from the surface connectivity. ---*/
16250 
16251  int *nElem_Send = new int[size+1]; nElem_Send[0] = 0;
16252  int *nElem_Recv = new int[size+1]; nElem_Recv[0] = 0;
16253  int *nElem_Flag = new int[size];
16254 
16255  for (int ii=0; ii < size; ii++) {
16256  nElem_Send[ii] = 0;
16257  nElem_Recv[ii] = 0;
16258  nElem_Flag[ii]= -1;
16259  }
16260  nElem_Send[size] = 0; nElem_Recv[size] = 0;
16261 
16262  /*--- Loop through our local line elements and check where each
16263  of the grid nodes resides based on global index. ---*/
16264 
16265  for (int ii = 0; ii < (int)nParallel_Line; ii++) {
16266  for ( int jj = 0; jj < N_POINTS_LINE; jj++ ) {
16267 
16268  /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/
16269 
16270  iNode = ii*N_POINTS_LINE+jj;
16271  Global_Index = Conn_BoundLine_Par[iNode]-1;
16272 
16273  /*--- Search for the processor that owns this point ---*/
16274 
16275  iProcessor = Global_Index/npoint_procs[0];
16276  if (iProcessor >= (unsigned long)size)
16277  iProcessor = (unsigned long)size-1;
16278  if (Global_Index >= nPoint_Linear_Nodes[iProcessor])
16279  while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++;
16280  else
16281  while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--;
16282 
16283  /*--- If we have not visited this element yet, increment our
16284  number of elements that must be sent to a particular proc. ---*/
16285 
16286  if ((nElem_Flag[iProcessor] != iNode)) {
16287  nElem_Flag[iProcessor] = iNode;
16288  nElem_Send[iProcessor+1]++;
16289  }
16290 
16291  }
16292  }
16293 
16294  /*--- Reset out flags and then loop through our local triangle surface
16295  elements performing the same check for where each grid node resides. ---*/
16296 
16297  for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1;
16298 
16299  for (int ii = 0; ii < (int)nParallel_BoundTria; ii++) {
16300  for ( int jj = 0; jj < N_POINTS_TRIANGLE; jj++ ) {
16301 
16302  /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/
16303 
16304  iNode = ii*N_POINTS_TRIANGLE + jj;
16305  Global_Index = Conn_BoundTria_Par[iNode]-1;
16306 
16307  /*--- Search for the processor that owns this point ---*/
16308 
16309  iProcessor = Global_Index/npoint_procs[0];
16310  if (iProcessor >= (unsigned long)size)
16311  iProcessor = (unsigned long)size-1;
16312  if (Global_Index >= nPoint_Linear_Nodes[iProcessor])
16313  while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++;
16314  else
16315  while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--;
16316 
16317  /*--- If we have not visited this element yet, increment our
16318  number of elements that must be sent to a particular proc. ---*/
16319 
16320  if ((nElem_Flag[iProcessor] != iNode)) {
16321  nElem_Flag[iProcessor] = iNode;
16322  nElem_Send[iProcessor+1]++;
16323  }
16324 
16325  }
16326  }
16327 
16328  /*--- Reset out flags and then loop through our local quad surface
16329  elements performing the same check for where each grid node resides. ---*/
16330 
16331  for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1;
16332 
16333  for (int ii = 0; ii < (int)nParallel_BoundQuad; ii++) {
16334  for ( int jj = 0; jj < N_POINTS_QUADRILATERAL; jj++ ) {
16335 
16336  /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/
16337 
16338  iNode = ii*N_POINTS_QUADRILATERAL+jj;
16339  Global_Index = Conn_BoundQuad_Par[iNode]-1;
16340 
16341  /*--- Search for the processor that owns this point ---*/
16342 
16343  iProcessor = Global_Index/npoint_procs[0];
16344  if (iProcessor >= (unsigned long)size)
16345  iProcessor = (unsigned long)size-1;
16346  if (Global_Index >= nPoint_Linear_Nodes[iProcessor])
16347  while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++;
16348  else
16349  while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--;
16350 
16351  /*--- If we have not visited this element yet, increment our
16352  number of elements that must be sent to a particular proc. ---*/
16353 
16354  if ((nElem_Flag[iProcessor] != iNode)) {
16355  nElem_Flag[iProcessor] = iNode;
16356  nElem_Send[iProcessor+1]++;
16357  }
16358 
16359  }
16360  }
16361 
16362  /*--- Communicate the number of nodes to be sent/recv'd amongst
16363  all processors. After this communication, each proc knows how
16364  many nodes it will receive from each other processor. ---*/
16365 
16366 #ifdef HAVE_MPI
16367  SU2_MPI::Alltoall(&(nElem_Send[1]), 1, MPI_INT,
16368  &(nElem_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD);
16369 #else
16370  nElem_Recv[1] = nElem_Send[1];
16371 #endif
16372 
16373  /*--- Prepare to send. First check how many
16374  messages we will be sending and receiving. Here we also put
16375  the counters into cumulative storage format to make the
16376  communications simpler. ---*/
16377 
16378  int nSends = 0, nRecvs = 0;
16379  for (int ii=0; ii < size; ii++) nElem_Flag[ii] = -1;
16380 
16381  for (int ii = 0; ii < size; ii++) {
16382  if ((ii != rank) && (nElem_Send[ii+1] > 0)) nSends++;
16383  if ((ii != rank) && (nElem_Recv[ii+1] > 0)) nRecvs++;
16384 
16385  nElem_Send[ii+1] += nElem_Send[ii];
16386  nElem_Recv[ii+1] += nElem_Recv[ii];
16387  }
16388 
16389  /*--- Allocate arrays for sending the global ID. ---*/
16390 
16391  unsigned long *idSend = new unsigned long[nElem_Send[size]];
16392  for (int ii = 0; ii < nElem_Send[size]; ii++) idSend[ii] = 0;
16393 
16394  /*--- Create an index variable to keep track of our index
16395  positions as we load up the send buffer. ---*/
16396 
16397  unsigned long *idIndex = new unsigned long[size];
16398  for (int ii=0; ii < size; ii++) idIndex[ii] = nElem_Send[ii];
16399 
16400  /*--- Now loop back through the local connectivities for the surface
16401  elements and load up the global IDs for sending to their home proc. ---*/
16402 
16403  for (int ii = 0; ii < (int)nParallel_Line; ii++) {
16404  for ( int jj = 0; jj < N_POINTS_LINE; jj++ ) {
16405 
16406  /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/
16407 
16408  iNode = ii*N_POINTS_LINE+jj;
16409  Global_Index = Conn_BoundLine_Par[iNode]-1;
16410 
16411  /*--- Search for the processor that owns this point ---*/
16412 
16413  iProcessor = Global_Index/npoint_procs[0];
16414  if (iProcessor >= (unsigned long)size)
16415  iProcessor = (unsigned long)size-1;
16416  if (Global_Index >= nPoint_Linear_Nodes[iProcessor])
16417  while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++;
16418  else
16419  while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--;
16420 
16421  /*--- Load global ID into the buffer for sending ---*/
16422 
16423  if (nElem_Flag[iProcessor] != iNode) {
16424 
16425  nElem_Flag[iProcessor] = iNode;
16426  unsigned long nn = idIndex[iProcessor];
16427 
16428  /*--- Load the connectivity values. ---*/
16429 
16430  idSend[nn] = Global_Index; nn++;
16431 
16432  /*--- Increment the index by the message length ---*/
16433 
16434  idIndex[iProcessor]++;
16435 
16436  }
16437 
16438  }
16439  }
16440 
16441  for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1;
16442 
16443  for (int ii = 0; ii < (int)nParallel_BoundTria; ii++) {
16444  for ( int jj = 0; jj < N_POINTS_TRIANGLE; jj++ ) {
16445 
16446  /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/
16447 
16448  iNode = ii*N_POINTS_TRIANGLE + jj;
16449  Global_Index = Conn_BoundTria_Par[iNode]-1;
16450 
16451  /*--- Search for the processor that owns this point ---*/
16452 
16453  iProcessor = Global_Index/npoint_procs[0];
16454  if (iProcessor >= (unsigned long)size)
16455  iProcessor = (unsigned long)size-1;
16456  if (Global_Index >= nPoint_Linear_Nodes[iProcessor])
16457  while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++;
16458  else
16459  while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--;
16460 
16461  /*--- Load global ID into the buffer for sending ---*/
16462 
16463  if (nElem_Flag[iProcessor] != iNode) {
16464 
16465  nElem_Flag[iProcessor] = iNode;
16466  unsigned long nn = idIndex[iProcessor];
16467 
16468  /*--- Load the connectivity values. ---*/
16469 
16470  idSend[nn] = Global_Index; nn++;
16471 
16472  /*--- Increment the index by the message length ---*/
16473 
16474  idIndex[iProcessor]++;
16475 
16476  }
16477 
16478  }
16479  }
16480 
16481  for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1;
16482 
16483  for (int ii = 0; ii < (int)nParallel_BoundQuad; ii++) {
16484  for ( int jj = 0; jj < N_POINTS_QUADRILATERAL; jj++ ) {
16485 
16486  /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/
16487 
16488  iNode = ii*N_POINTS_QUADRILATERAL+jj;
16489  Global_Index = Conn_BoundQuad_Par[iNode]-1;
16490 
16491  /*--- Search for the processor that owns this point ---*/
16492 
16493  iProcessor = Global_Index/npoint_procs[0];
16494  if (iProcessor >= (unsigned long)size)
16495  iProcessor = (unsigned long)size-1;
16496  if (Global_Index >= nPoint_Linear_Nodes[iProcessor])
16497  while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++;
16498  else
16499  while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--;
16500 
16501  /*--- Load global ID into the buffer for sending ---*/
16502 
16503  if (nElem_Flag[iProcessor] != iNode) {
16504 
16505  nElem_Flag[iProcessor] = iNode;
16506  unsigned long nn = idIndex[iProcessor];
16507 
16508  /*--- Load the connectivity values. ---*/
16509 
16510  idSend[nn] = Global_Index; nn++;
16511 
16512  /*--- Increment the index by the message length ---*/
16513 
16514  idIndex[iProcessor]++;
16515 
16516  }
16517 
16518  }
16519  }
16520 
16521  /*--- Allocate the memory that we need for receiving the global IDs
16522  values and then cue up the non-blocking receives. Note that
16523  we do not include our own rank in the communications. We will
16524  directly copy our own data later. ---*/
16525 
16526  unsigned long *idRecv = NULL;
16527  idRecv = new unsigned long[nElem_Recv[size]];
16528  for (int ii = 0; ii < nElem_Recv[size]; ii++)
16529  idRecv[ii] = 0;
16530 
16531 #ifdef HAVE_MPI
16532  /*--- We need double the number of messages to send both the conn.
16533  and the flags for the halo cells. ---*/
16534 
16535  send_req = new SU2_MPI::Request[nSends];
16536  recv_req = new SU2_MPI::Request[nRecvs];
16537 
16538  /*--- Launch the non-blocking recv's for the global IDs. ---*/
16539 
16540  unsigned long iMessage = 0;
16541  for (int ii=0; ii<size; ii++) {
16542  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
16543  int ll = nElem_Recv[ii];
16544  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
16545  int count = kk;
16546  int source = ii;
16547  int tag = ii + 1;
16548  SU2_MPI::Irecv(&(idRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
16549  MPI_COMM_WORLD, &(recv_req[iMessage]));
16550  iMessage++;
16551  }
16552  }
16553 
16554  /*--- Launch the non-blocking sends of the global IDs. ---*/
16555 
16556  iMessage = 0;
16557  for (int ii=0; ii<size; ii++) {
16558  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
16559  int ll = nElem_Send[ii];
16560  int kk = nElem_Send[ii+1] - nElem_Send[ii];
16561  int count = kk;
16562  int dest = ii;
16563  int tag = rank + 1;
16564  SU2_MPI::Isend(&(idSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
16565  MPI_COMM_WORLD, &(send_req[iMessage]));
16566  iMessage++;
16567  }
16568  }
16569 #endif
16570 
16571  /*--- Copy my own rank's data into the recv buffer directly. ---*/
16572 
16573  int mm = nElem_Recv[rank];
16574  int ll = nElem_Send[rank];
16575  int kk = nElem_Send[rank+1];
16576 
16577  for (int nn=ll; nn<kk; nn++, mm++) idRecv[mm] = idSend[nn];
16578 
16579  /*--- Wait for the non-blocking sends and recvs to complete. ---*/
16580 
16581 #ifdef HAVE_MPI
16582  int number = nSends;
16583  for (int ii = 0; ii < number; ii++)
16584  SU2_MPI::Waitany(number, send_req, &ind, &status);
16585 
16586  number = nRecvs;
16587  for (int ii = 0; ii < number; ii++)
16588  SU2_MPI::Waitany(number, recv_req, &ind, &status);
16589 
16590  delete [] send_req;
16591  delete [] recv_req;
16592 #endif
16593 
16594  /*--------------------------------------------------------------------------*/
16595  /*--- Step 2: Each proc now knows which is its local grid nodes from ---*/
16596  /*--- the entire volume solution are part of the surface. We ---*/
16597  /*--- now apply a mask to extract just those points on the ---*/
16598  /*--- surface. We also need to perform a renumbering so that ---*/
16599  /*--- the surface data (nodes and connectivity) have their ---*/
16600  /*--- own global numbering. This is important for writing ---*/
16601  /*--- output files in a later routine. ---*/
16602  /*--------------------------------------------------------------------------*/
16603 
16604  /*--- Create a local data structure that acts as a mask to extract the
16605  set of points within the local set that are on the surface. ---*/
16606 
16607  int *surfPoint = new int[nParallel_Poin];
16608  for (iPoint = 0; iPoint < nParallel_Poin; iPoint++) surfPoint[iPoint] = -1;
16609 
16610  for (int ii = 0; ii < nElem_Recv[size]; ii++) {
16611  surfPoint[(int)idRecv[ii]- starting_node[rank]] = (int)idRecv[ii];
16612  }
16613 
16614  /*--- First, add up the number of surface points I have on my rank. ---*/
16615 
16616  nSurf_Poin_Par = 0;
16617  for (iPoint = 0; iPoint < nParallel_Poin; iPoint++) {
16618  if (surfPoint[iPoint] != -1) {
16619  nSurf_Poin_Par++;
16620  }
16621  }
16622 
16623  /*--- Communicate this number of local surface points to all other
16624  processors so that it can be used to create offsets for the new
16625  global numbering for the surface points. ---*/
16626 
16627  int *nPoint_Send = new int[size+1]; nPoint_Send[0] = 0;
16628  int *nPoint_Recv = new int[size+1]; nPoint_Recv[0] = 0;
16629 
16630  for (int ii=1; ii < size+1; ii++) nPoint_Send[ii]= (int)nSurf_Poin_Par;
16631 
16632 #ifdef HAVE_MPI
16633  SU2_MPI::Alltoall(&(nPoint_Send[1]), 1, MPI_INT,
16634  &(nPoint_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD);
16635 #else
16636  nPoint_Recv[1] = nPoint_Send[1];
16637 #endif
16638 
16639  /*--- Go to cumulative storage format to compute the offsets. ---*/
16640 
16641  for (int ii = 0; ii < size; ii++) {
16642  nPoint_Send[ii+1] += nPoint_Send[ii];
16643  nPoint_Recv[ii+1] += nPoint_Recv[ii];
16644  }
16645 
16646  /*--- Now that we know the number of local surface points that we have,
16647  we can allocate the new data structure to hold these points alone. Here,
16648  we also copy the data for those points from our volume data structure. ---*/
16649 
16650  Parallel_Surf_Data = new su2double*[VARS_PER_POINT];
16651  for (int jj = 0; jj < VARS_PER_POINT; jj++) {
16652  Parallel_Surf_Data[jj] = new su2double[nSurf_Poin_Par];
16653  count = 0;
16654  for (int ii = 0; ii < (int)nParallel_Poin; ii++) {
16655  if (surfPoint[ii] !=-1) {
16656  Parallel_Surf_Data[jj][count] = Parallel_Data[jj][ii];
16657  count++;
16658  }
16659  }
16660  }
16661 
16662  /*--- Reduce the total number of surf points we have. This will be
16663  needed for writing the surface solution files later. ---*/
16664 
16665 #ifndef HAVE_MPI
16666  nGlobal_Surf_Poin = nSurf_Poin_Par;
16667 #else
16668  SU2_MPI::Allreduce(&nSurf_Poin_Par, &nGlobal_Surf_Poin, 1,
16670 #endif
16671 
16672  /*--- Now that we know every proc's global offset for the number of
16673  surface points, we can create the new global numbering. Here, we
16674  create a new mapping using two arrays, which will need to be
16675  communicated. We use our mask again here. ---*/
16676 
16677  unsigned long *globalP = new unsigned long[nSurf_Poin_Par];
16678  unsigned long *renumbP = new unsigned long[nSurf_Poin_Par];
16679 
16680  count = 0;
16681  for (iPoint = 0; iPoint < nParallel_Poin; iPoint++) {
16682  if (surfPoint[iPoint] != -1) {
16683  globalP[count] = surfPoint[iPoint];
16684  renumbP[count] = count + nPoint_Recv[rank];
16685  count++;
16686  }
16687  }
16688 
16689  /*--------------------------------------------------------------------------*/
16690  /*--- Step 3: Communicate the arrays with the new global surface point ---*/
16691  /*--- numbering to the procs that hold the connectivity for ---*/
16692  /*--- each element. This will be done in two phases. First, ---*/
16693  /*--- we send the arrays around to the other procs based on ---*/
16694  /*--- the linear partitioning for the elems. This gets us ---*/
16695  /*--- most of the way there, however, due to the type of ---*/
16696  /*--- linear partitioning for the elements, there may exist ---*/
16697  /*--- elements that have nodes outside of the linear part. ---*/
16698  /*--- bounds. This is because the elems are distributed based ---*/
16699  /*--- on the node with the smallest global ID. ---*/
16700  /*--------------------------------------------------------------------------*/
16701 
16702  /*--- First, we perform the linear partitioning again as it is done
16703  for elements, which is slightly different than for nodes (above). ---*/
16704 
16705  /*--- Force the removal of all added periodic elements (use global index).
16706  First, we isolate and create a list of all added periodic points, excluding
16707  those that were part of the original domain (we want these to be in the
16708  output files). ---*/
16709 
16710  vector<unsigned long> Added_Periodic;
16711  Added_Periodic.clear();
16712 
16713  if (config->GetKind_SU2() != SU2_DEF) {
16714  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
16715  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
16716  SendRecv = config->GetMarker_All_SendRecv(iMarker);
16717  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
16718  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
16719 
16720  if ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
16721  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 0) &&
16722  (SendRecv < 0)) {
16723  Added_Periodic.push_back(geometry->node[iPoint]->GetGlobalIndex());
16724  }
16725  }
16726  }
16727  }
16728  }
16729 
16730  /*--- Now we communicate this information to all processors, so that they
16731  can force the removal of these particular nodes by flagging them as halo
16732  points. In general, this should be a small percentage of the total mesh,
16733  so the communication/storage costs here shouldn't be prohibitive. ---*/
16734 
16735  /*--- First communicate the number of points that each rank has found. ---*/
16736 
16737  unsigned long nAddedPeriodic = 0, maxAddedPeriodic = 0;
16738  unsigned long Buffer_Send_nAddedPeriodic[1], *Buffer_Recv_nAddedPeriodic = NULL;
16739  Buffer_Recv_nAddedPeriodic = new unsigned long[size];
16740 
16741  nAddedPeriodic = Added_Periodic.size();
16742  Buffer_Send_nAddedPeriodic[0] = nAddedPeriodic;
16743 
16744 #ifdef HAVE_MPI
16745  SU2_MPI::Allreduce(&nAddedPeriodic, &maxAddedPeriodic, 1, MPI_UNSIGNED_LONG,
16747  SU2_MPI::Allgather(&Buffer_Send_nAddedPeriodic, 1, MPI_UNSIGNED_LONG,
16748  Buffer_Recv_nAddedPeriodic, 1, MPI_UNSIGNED_LONG, MPI_COMM_WORLD);
16749 #else
16750  maxAddedPeriodic = nAddedPeriodic;
16751  Buffer_Recv_nAddedPeriodic[0] = Buffer_Send_nAddedPeriodic[0];
16752 #endif
16753 
16754  /*--- Communicate the global index values of all added periodic nodes. ---*/
16755  unsigned long *Buffer_Send_AddedPeriodic = new unsigned long[maxAddedPeriodic];
16756  unsigned long *Buffer_Recv_AddedPeriodic = new unsigned long[size*maxAddedPeriodic];
16757 
16758  for (iPoint = 0; iPoint < Added_Periodic.size(); iPoint++) {
16759  Buffer_Send_AddedPeriodic[iPoint] = Added_Periodic[iPoint];
16760  }
16761 
16762  /*--- Gather the element connectivity information. All processors will now
16763  have a copy of the global index values for all added periodic points. ---*/
16764 
16765 #ifdef HAVE_MPI
16766  SU2_MPI::Allgather(Buffer_Send_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
16767  Buffer_Recv_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG,
16768  MPI_COMM_WORLD);
16769 #else
16770  for (iPoint = 0; iPoint < maxAddedPeriodic; iPoint++)
16771  Buffer_Recv_AddedPeriodic[iPoint] = Buffer_Send_AddedPeriodic[iPoint];
16772 #endif
16773 
16774  /*--- Search all send/recv boundaries on this partition for halo cells. In
16775  particular, consider only the recv conditions (these are the true halo
16776  nodes). Check the ranks of the processors that are communicating and
16777  choose to keep only the halo cells from the higher rank processor. Here,
16778  we are also choosing to keep periodic nodes that were part of the original
16779  domain. We will check the communicated list of added periodic points. ---*/
16780 
16781  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
16782  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
16783 
16784  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
16785  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
16786  SendRecv = config->GetMarker_All_SendRecv(iMarker);
16787  RecvFrom = abs(SendRecv)-1;
16788 
16789  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
16790  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
16791  Global_Index = geometry->node[iPoint]->GetGlobalIndex();
16792 
16793  /*--- We need to keep one copy of overlapping halo cells. ---*/
16794 
16795  notHalo = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() == 0) &&
16796  (SendRecv < 0) && (rank > RecvFrom));
16797 
16798  /*--- We want to keep the periodic nodes that were part of the original domain.
16799  For SU2_DEF we want to keep all periodic nodes. ---*/
16800 
16801  if (config->GetKind_SU2() == SU2_DEF) {
16802  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0));
16803  }else {
16804  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
16805  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
16806  }
16807 
16808  notPeriodic = (isPeriodic && (SendRecv < 0));
16809 
16810  /*--- Lastly, check that this isn't an added periodic point that
16811  we will forcibly remove. Use the communicated list of these points. ---*/
16812 
16813  addedPeriodic = false; kPoint = 0;
16814  for (iProcessor = 0; iProcessor < (unsigned long)size; iProcessor++) {
16815  for (jPoint = 0; jPoint < Buffer_Recv_nAddedPeriodic[iProcessor]; jPoint++) {
16816  if (Global_Index == Buffer_Recv_AddedPeriodic[kPoint+jPoint])
16817  addedPeriodic = true;
16818  }
16819 
16820  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
16821 
16822  kPoint = (iProcessor+1)*maxAddedPeriodic;
16823 
16824  }
16825 
16826  /*--- If we found either of these types of nodes, flag them to be kept. ---*/
16827 
16828  if ((notHalo || notPeriodic) && !addedPeriodic) {
16829  Local_Halo[iPoint] = false;
16830  }
16831 
16832  }
16833  }
16834  }
16835 
16836  /*--- Now that we've done the gymnastics to find any periodic points,
16837  compute the total number of local and global points for the output. ---*/
16838 
16839  nLocalPoint = 0;
16840  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
16841  if (Local_Halo[iPoint] == false)
16842  nLocalPoint++;
16843 
16844 #ifdef HAVE_MPI
16845  SU2_MPI::Allreduce(&nLocalPoint, &nTotalPoint, 1,
16847 #else
16848  nTotalPoint = nLocalPoint;
16849 #endif
16850 
16851  /*--- Compute the number of points that will be on each processor.
16852  This is a linear partitioning with the addition of a simple load
16853  balancing for any remainder points. ---*/
16854 
16855  total_pt_accounted = 0;
16856  for (int ii = 0; ii < size; ii++) {
16857  npoint_procs[ii] = nTotalPoint/size;
16858  total_pt_accounted = total_pt_accounted + npoint_procs[ii];
16859  }
16860 
16861  /*--- Get the number of remainder points after the even division. ---*/
16862 
16863  rem_points = nTotalPoint-total_pt_accounted;
16864  for (unsigned long ii = 0; ii < rem_points; ii++) {
16865  npoint_procs[ii]++;
16866  }
16867 
16868  /*--- Store the local number of nodes and the beginning/end index ---*/
16869 
16870  starting_node[0] = 0;
16871  ending_node[0] = starting_node[0] + npoint_procs[0];
16872  nPoint_Linear_Elems[0] = 0;
16873  for (int ii = 1; ii < size; ii++) {
16874  starting_node[ii] = ending_node[ii-1];
16875  ending_node[ii] = starting_node[ii] + npoint_procs[ii];
16876  nPoint_Linear_Elems[ii] = nPoint_Linear_Elems[ii-1] + npoint_procs[ii-1];
16877  }
16878  nPoint_Linear_Elems[size] = nTotalPoint;
16879 
16880  /*--- Reset our flags and counters ---*/
16881 
16882  for (int ii=0; ii < size; ii++) {
16883  nElem_Send[ii] = 0;
16884  nElem_Recv[ii] = 0;
16885  nElem_Flag[ii]= -1;
16886  }
16887  nElem_Send[size] = 0; nElem_Recv[size] = 0;
16888 
16889  /*--- Loop through my local surface nodes, find which proc the global
16890  value lives on, then communicate the global ID and remumbered value. ---*/
16891 
16892  for (int ii = 0; ii < (int)nSurf_Poin_Par; ii++) {
16893 
16894  Global_Index = globalP[ii];
16895 
16896  /*--- Search for the processor that owns this point ---*/
16897 
16898  iProcessor = Global_Index/npoint_procs[0];
16899  if (iProcessor >= (unsigned long)size)
16900  iProcessor = (unsigned long)size-1;
16901  if (Global_Index >= nPoint_Linear_Elems[iProcessor])
16902  while(Global_Index >= nPoint_Linear_Elems[iProcessor+1]) iProcessor++;
16903  else
16904  while(Global_Index < nPoint_Linear_Elems[iProcessor]) iProcessor--;
16905 
16906  /*--- If we have not visited this element yet, increment our
16907  number of elements that must be sent to a particular proc. ---*/
16908 
16909  if ((nElem_Flag[iProcessor] != ii)) {
16910  nElem_Flag[iProcessor] = ii;
16911  nElem_Send[iProcessor+1]++;
16912  }
16913 
16914  }
16915 
16916  /*--- Communicate the number of cells to be sent/recv'd amongst
16917  all processors. After this communication, each proc knows how
16918  many cells it will receive from each other processor. ---*/
16919 
16920 #ifdef HAVE_MPI
16921  SU2_MPI::Alltoall(&(nElem_Send[1]), 1, MPI_INT,
16922  &(nElem_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD);
16923 #else
16924  nElem_Recv[1] = nElem_Send[1];
16925 #endif
16926 
16927  /*--- Prepare to send. First check how many
16928  messages we will be sending and receiving. Here we also put
16929  the counters into cumulative storage format to make the
16930  communications simpler. ---*/
16931 
16932  nSends = 0; nRecvs = 0;
16933  for (int ii=0; ii < size; ii++) nElem_Flag[ii] = -1;
16934 
16935  for (int ii = 0; ii < size; ii++) {
16936  if ((ii != rank) && (nElem_Send[ii+1] > 0)) nSends++;
16937  if ((ii != rank) && (nElem_Recv[ii+1] > 0)) nRecvs++;
16938 
16939  nElem_Send[ii+1] += nElem_Send[ii];
16940  nElem_Recv[ii+1] += nElem_Recv[ii];
16941  }
16942 
16943  /*--- Allocate memory to hold the globals that we are
16944  sending. ---*/
16945 
16946  unsigned long *globalSend = NULL;
16947  globalSend = new unsigned long[nElem_Send[size]];
16948  for (int ii = 0; ii < nElem_Send[size]; ii++)
16949  globalSend[ii] = 0;
16950 
16951  /*--- Allocate memory to hold the renumbering that we are
16952  sending. ---*/
16953 
16954  unsigned long *renumbSend = NULL;
16955  renumbSend = new unsigned long[nElem_Send[size]];
16956  for (int ii = 0; ii < nElem_Send[size]; ii++)
16957  renumbSend[ii] = 0;
16958 
16959  /*--- Create an index variable to keep track of our index
16960  position as we load up the send buffer. ---*/
16961 
16962  unsigned long *index = new unsigned long[size];
16963  for (int ii=0; ii < size; ii++) index[ii] = nElem_Send[ii];
16964 
16965  /*--- Loop back through and load up the buffers for the global IDs
16966  and their new renumbering values. ---*/
16967 
16968  for (int ii = 0; ii < (int)nSurf_Poin_Par; ii++) {
16969 
16970  Global_Index = globalP[ii];
16971 
16972  /*--- Search for the processor that owns this point ---*/
16973 
16974  iProcessor = Global_Index/npoint_procs[0];
16975  if (iProcessor >= (unsigned long)size)
16976  iProcessor = (unsigned long)size-1;
16977  if (Global_Index >= nPoint_Linear_Elems[iProcessor])
16978  while(Global_Index >= nPoint_Linear_Elems[iProcessor+1]) iProcessor++;
16979  else
16980  while(Global_Index < nPoint_Linear_Elems[iProcessor]) iProcessor--;
16981 
16982 
16983  if (nElem_Flag[iProcessor] != ii) {
16984 
16985  nElem_Flag[iProcessor] = ii;
16986  unsigned long nn = index[iProcessor];
16987 
16988  globalSend[nn] = Global_Index;
16989  renumbSend[nn] = renumbP[ii];
16990 
16991  /*--- Increment the index by the message length ---*/
16992 
16993  index[iProcessor]++;
16994 
16995  }
16996  }
16997 
16998  /*--- Free memory after loading up the send buffer. ---*/
16999 
17000  delete [] index;
17001 
17002  /*--- Allocate the memory that we need for receiving the
17003  values and then cue up the non-blocking receives. Note that
17004  we do not include our own rank in the communications. We will
17005  directly copy our own data later. ---*/
17006 
17007  unsigned long *globalRecv = NULL;
17008  globalRecv = new unsigned long[nElem_Recv[size]];
17009  for (int ii = 0; ii < nElem_Recv[size]; ii++)
17010  globalRecv[ii] = 0;
17011 
17012  unsigned long *renumbRecv = NULL;
17013  renumbRecv = new unsigned long[nElem_Recv[size]];
17014  for (int ii = 0; ii < nElem_Recv[size]; ii++)
17015  renumbRecv[ii] = 0;
17016 
17017 #ifdef HAVE_MPI
17018  /*--- We need double the number of messages to send both the conn.
17019  and the flags for the halo cells. ---*/
17020 
17021  send_req = new SU2_MPI::Request[2*nSends];
17022  recv_req = new SU2_MPI::Request[2*nRecvs];
17023 
17024  /*--- Launch the non-blocking recv's for the global ID. ---*/
17025 
17026  iMessage = 0;
17027  for (int ii=0; ii<size; ii++) {
17028  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
17029  int ll = nElem_Recv[ii];
17030  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
17031  int count = kk;
17032  int source = ii;
17033  int tag = ii + 1;
17034  SU2_MPI::Irecv(&(globalRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
17035  MPI_COMM_WORLD, &(recv_req[iMessage]));
17036  iMessage++;
17037  }
17038  }
17039 
17040  /*--- Launch the non-blocking sends of the global ID. ---*/
17041 
17042  iMessage = 0;
17043  for (int ii=0; ii<size; ii++) {
17044  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
17045  int ll = nElem_Send[ii];
17046  int kk = nElem_Send[ii+1] - nElem_Send[ii];
17047  int count = kk;
17048  int dest = ii;
17049  int tag = rank + 1;
17050  SU2_MPI::Isend(&(globalSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
17051  MPI_COMM_WORLD, &(send_req[iMessage]));
17052  iMessage++;
17053  }
17054  }
17055 
17056  /*--- Launch the non-blocking recv's for the renumbered ID. ---*/
17057 
17058  iMessage = 0;
17059  for (int ii=0; ii<size; ii++) {
17060  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
17061  int ll = nElem_Recv[ii];
17062  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
17063  int count = kk;
17064  int source = ii;
17065  int tag = ii + 1;
17066  SU2_MPI::Irecv(&(renumbRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
17067  MPI_COMM_WORLD, &(recv_req[iMessage+nRecvs]));
17068  iMessage++;
17069  }
17070  }
17071 
17072  /*--- Launch the non-blocking sends of the renumbered ID. ---*/
17073 
17074  iMessage = 0;
17075  for (int ii=0; ii<size; ii++) {
17076  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
17077  int ll = nElem_Send[ii];
17078  int kk = nElem_Send[ii+1] - nElem_Send[ii];
17079  int count = kk;
17080  int dest = ii;
17081  int tag = rank + 1;
17082  SU2_MPI::Isend(&(renumbSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
17083  MPI_COMM_WORLD, &(send_req[iMessage+nSends]));
17084  iMessage++;
17085  }
17086  }
17087 
17088 #endif
17089 
17090  /*--- Load our own procs data into the buffers directly. ---*/
17091 
17092  mm = nElem_Recv[rank];
17093  ll = nElem_Send[rank];
17094  kk = nElem_Send[rank+1];
17095 
17096  for (int nn=ll; nn<kk; nn++, mm++) globalRecv[mm] = globalSend[nn];
17097 
17098  mm = nElem_Recv[rank];
17099  ll = nElem_Send[rank];
17100  kk = nElem_Send[rank+1];
17101 
17102  for (int nn=ll; nn<kk; nn++, mm++) renumbRecv[mm] = renumbSend[nn];
17103 
17104  /*--- Wait for the non-blocking sends and recvs to complete. ---*/
17105 
17106 #ifdef HAVE_MPI
17107  number = 2*nSends;
17108  for (int ii = 0; ii < number; ii++)
17109  SU2_MPI::Waitany(number, send_req, &ind, &status);
17110 
17111  number = 2*nRecvs;
17112  for (int ii = 0; ii < number; ii++)
17113  SU2_MPI::Waitany(number, recv_req, &ind, &status);
17114 
17115  delete [] send_req;
17116  delete [] recv_req;
17117 #endif
17118 
17119  /*-- Now update my local connectivitiy for the surface with the new
17120  numbering. Create a new mapping for global -> renumber for nodes. Note
17121  the adding of 1 back in here for the eventual viz. purposes. ---*/
17122 
17123  map<unsigned long,unsigned long> Global2Renumber;
17124  for (int ii = 0; ii < nElem_Recv[size]; ii++) {
17125  Global2Renumber[globalRecv[ii]] = renumbRecv[ii] + 1;
17126  }
17127 
17128 
17129  /*--- The final step is one last pass over all elements to check
17130  for points outside of the linear partitions of the elements. Again,
17131  note that elems were distributed based on their smallest global ID,
17132  so some nodes of the elem may have global IDs lying outside of the
17133  linear partitioning. We need to recover the mapping for these
17134  outliers. We loop over all local surface elements to find these. ---*/
17135 
17136  vector<unsigned long>::iterator it;
17137  vector<unsigned long> outliers;
17138 
17139  for (int ii = 0; ii < (int)nParallel_Line; ii++) {
17140  for ( int jj = 0; jj < N_POINTS_LINE; jj++ ) {
17141 
17142  iNode = ii*N_POINTS_LINE+jj;
17143  Global_Index = Conn_BoundLine_Par[iNode]-1;
17144 
17145  /*--- Search for the processor that owns this point ---*/
17146 
17147  iProcessor = Global_Index/npoint_procs[0];
17148  if (iProcessor >= (unsigned long)size)
17149  iProcessor = (unsigned long)size-1;
17150  if (Global_Index >= nPoint_Linear_Elems[iProcessor])
17151  while(Global_Index >= nPoint_Linear_Elems[iProcessor+1]) iProcessor++;
17152  else
17153  while(Global_Index < nPoint_Linear_Elems[iProcessor]) iProcessor--;
17154 
17155  /*--- Store the global ID if it is outside our own linear partition. ---*/
17156 
17157  if ((iProcessor != (unsigned long)rank)) {
17158  outliers.push_back(Global_Index);
17159  }
17160 
17161  }
17162  }
17163 
17164  for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1;
17165 
17166  for (int ii = 0; ii < (int)nParallel_BoundTria; ii++) {
17167  for ( int jj = 0; jj < N_POINTS_TRIANGLE; jj++ ) {
17168 
17169  iNode = ii*N_POINTS_TRIANGLE + jj;
17170  Global_Index = Conn_BoundTria_Par[iNode]-1;
17171 
17172  /*--- Search for the processor that owns this point ---*/
17173 
17174  iProcessor = Global_Index/npoint_procs[0];
17175  if (iProcessor >= (unsigned long)size)
17176  iProcessor = (unsigned long)size-1;
17177  if (Global_Index >= nPoint_Linear_Elems[iProcessor])
17178  while(Global_Index >= nPoint_Linear_Elems[iProcessor+1]) iProcessor++;
17179  else
17180  while(Global_Index < nPoint_Linear_Elems[iProcessor]) iProcessor--;
17181 
17182  /*--- Store the global ID if it is outside our own linear partition. ---*/
17183 
17184  if ((iProcessor != (unsigned long)rank)) {
17185  outliers.push_back(Global_Index);
17186  }
17187 
17188  }
17189  }
17190 
17191  for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1;
17192 
17193  for (int ii = 0; ii < (int)nParallel_BoundQuad; ii++) {
17194  for ( int jj = 0; jj < N_POINTS_QUADRILATERAL; jj++ ) {
17195 
17196  iNode = ii*N_POINTS_QUADRILATERAL+jj;
17197  Global_Index = Conn_BoundQuad_Par[iNode]-1;
17198 
17199  /*--- Search for the processor that owns this point ---*/
17200 
17201  iProcessor = Global_Index/npoint_procs[0];
17202  if (iProcessor >= (unsigned long)size)
17203  iProcessor = (unsigned long)size-1;
17204  if (Global_Index >= nPoint_Linear_Elems[iProcessor])
17205  while(Global_Index >= nPoint_Linear_Elems[iProcessor+1]) iProcessor++;
17206  else
17207  while(Global_Index < nPoint_Linear_Elems[iProcessor]) iProcessor--;
17208 
17209  /*--- Store the global ID if it is outside our own linear partition. ---*/
17210 
17211  if ((iProcessor != (unsigned long)rank)) {
17212  outliers.push_back(Global_Index);
17213  }
17214 
17215  }
17216  }
17217 
17218  /*--- Create a unique list of global IDs that fall outside of our procs
17219  linear partition. ---*/
17220 
17221  sort(outliers.begin(), outliers.end());
17222  it = unique(outliers.begin(), outliers.end());
17223  outliers.resize(it - outliers.begin());
17224 
17225  /*--- Now loop over the outliers and communicate to those procs that
17226  hold the new numbering for our outlier points. We need to ask for the
17227  new numbering from these procs. ---*/
17228 
17229  for (int ii=0; ii < size; ii++) {
17230  nElem_Send[ii] = 0;
17231  nElem_Recv[ii] = 0;
17232  nElem_Flag[ii]= -1;
17233  }
17234  nElem_Send[size] = 0; nElem_Recv[size] = 0;
17235 
17236  for (int ii = 0; ii < (int)outliers.size(); ii++) {
17237 
17238  Global_Index = outliers[ii];
17239 
17240  /*--- Search for the processor that owns this point ---*/
17241 
17242  iProcessor = Global_Index/npoint_procs[0];
17243  if (iProcessor >= (unsigned long)size)
17244  iProcessor = (unsigned long)size-1;
17245  if (Global_Index >= nPoint_Linear_Nodes[iProcessor])
17246  while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++;
17247  else
17248  while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--;
17249 
17250  /*--- If we have not visited this element yet, increment our
17251  number of elements that must be sent to a particular proc. ---*/
17252 
17253  if ((nElem_Flag[iProcessor] != ii)) {
17254  nElem_Flag[iProcessor] = ii;
17255  nElem_Send[iProcessor+1]++;
17256  }
17257 
17258  }
17259 
17260  /*--- Communicate the number of cells to be sent/recv'd amongst
17261  all processors. After this communication, each proc knows how
17262  many cells it will receive from each other processor. ---*/
17263 
17264 #ifdef HAVE_MPI
17265  SU2_MPI::Alltoall(&(nElem_Send[1]), 1, MPI_INT,
17266  &(nElem_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD);
17267 #else
17268  nElem_Recv[1] = nElem_Send[1];
17269 #endif
17270 
17271  /*--- Prepare to send connectivities. First check how many
17272  messages we will be sending and receiving. Here we also put
17273  the counters into cumulative storage format to make the
17274  communications simpler. ---*/
17275 
17276  nSends = 0; nRecvs = 0;
17277  for (int ii=0; ii < size; ii++) nElem_Flag[ii] = -1;
17278 
17279  for (int ii = 0; ii < size; ii++) {
17280  if ((ii != rank) && (nElem_Send[ii+1] > 0)) nSends++;
17281  if ((ii != rank) && (nElem_Recv[ii+1] > 0)) nRecvs++;
17282 
17283  nElem_Send[ii+1] += nElem_Send[ii];
17284  nElem_Recv[ii+1] += nElem_Recv[ii];
17285  }
17286 
17287  delete [] idSend;
17288  idSend = new unsigned long[nElem_Send[size]];
17289  for (int ii = 0; ii < nElem_Send[size]; ii++)
17290  idSend[ii] = 0;
17291 
17292  /*--- Reset our index variable for reuse. ---*/
17293 
17294  for (int ii=0; ii < size; ii++) idIndex[ii] = nElem_Send[ii];
17295 
17296  /*--- Loop over the outliers again and load up the global IDs. ---*/
17297 
17298  for (int ii = 0; ii < (int)outliers.size(); ii++) {
17299 
17300  Global_Index = outliers[ii];
17301 
17302  /*--- Search for the processor that owns this point ---*/
17303 
17304  iProcessor = Global_Index/npoint_procs[0];
17305  if (iProcessor >= (unsigned long)size)
17306  iProcessor = (unsigned long)size-1;
17307  if (Global_Index >= nPoint_Linear_Nodes[iProcessor])
17308  while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++;
17309  else
17310  while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--;
17311 
17312  /*--- If we have not visited this element yet, increment our
17313  number of elements that must be sent to a particular proc. ---*/
17314 
17315  if ((nElem_Flag[iProcessor] != ii)) {
17316 
17317  nElem_Flag[iProcessor] = ii;
17318  unsigned long nn = idIndex[iProcessor];
17319 
17320  /*--- Load the global ID values. ---*/
17321 
17322  idSend[nn] = Global_Index; nn++;
17323 
17324  /*--- Increment the index by the message length ---*/
17325 
17326  idIndex[iProcessor]++;
17327 
17328  }
17329  }
17330 
17331  /*--- Allocate the memory that we need for receiving the
17332  values and then cue up the non-blocking receives. Note that
17333  we do not include our own rank in the communications. We will
17334  directly copy our own data later. ---*/
17335 
17336  delete [] idRecv;
17337  idRecv = new unsigned long[nElem_Recv[size]];
17338  for (int ii = 0; ii < nElem_Recv[size]; ii++)
17339  idRecv[ii] = 0;
17340 
17341 #ifdef HAVE_MPI
17342  /*--- We need double the number of messages to send both the conn.
17343  and the flags for the halo cells. ---*/
17344 
17345  send_req = new SU2_MPI::Request[nSends];
17346  recv_req = new SU2_MPI::Request[nRecvs];
17347 
17348  /*--- Launch the non-blocking recv's for the connectivity. ---*/
17349 
17350  iMessage = 0;
17351  for (int ii=0; ii<size; ii++) {
17352  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
17353  int ll = nElem_Recv[ii];
17354  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
17355  int count = kk;
17356  int source = ii;
17357  int tag = ii + 1;
17358  SU2_MPI::Irecv(&(idRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
17359  MPI_COMM_WORLD, &(recv_req[iMessage]));
17360  iMessage++;
17361  }
17362  }
17363 
17364  /*--- Launch the non-blocking sends of the connectivity. ---*/
17365 
17366  iMessage = 0;
17367  for (int ii=0; ii<size; ii++) {
17368  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
17369  int ll = nElem_Send[ii];
17370  int kk = nElem_Send[ii+1] - nElem_Send[ii];
17371  int count = kk;
17372  int dest = ii;
17373  int tag = rank + 1;
17374  SU2_MPI::Isend(&(idSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
17375  MPI_COMM_WORLD, &(send_req[iMessage]));
17376  iMessage++;
17377  }
17378  }
17379 #endif
17380 
17381  /*--- Copy my own rank's data into the recv buffer directly. ---*/
17382 
17383  mm = nElem_Recv[rank];
17384  ll = nElem_Send[rank];
17385  kk = nElem_Send[rank+1];
17386 
17387  for (int nn=ll; nn<kk; nn++, mm++) idRecv[mm] = idSend[nn];
17388 
17389  /*--- Wait for the non-blocking sends and recvs to complete. ---*/
17390 
17391 #ifdef HAVE_MPI
17392  number = nSends;
17393  for (int ii = 0; ii < number; ii++)
17394  SU2_MPI::Waitany(number, send_req, &ind, &status);
17395 
17396  number = nRecvs;
17397  for (int ii = 0; ii < number; ii++)
17398  SU2_MPI::Waitany(number, recv_req, &ind, &status);
17399 
17400  delete [] send_req;
17401  delete [] recv_req;
17402 #endif
17403 
17404  /*--- The procs holding the outlier grid nodes now have the global IDs
17405  that they need to have their renumbering shared. ---*/
17406 
17407  for (int ii = 0; ii < nElem_Recv[size]; ii++) {
17408  for (iPoint = 0; iPoint < nSurf_Poin_Par; iPoint++) {
17409  if (idRecv[ii] == globalP[iPoint]) {
17410  idRecv[ii] = renumbP[iPoint];
17411  }
17412  }
17413  }
17414 
17415  /*--- Now simply reverse the last communication to give the renumbered IDs
17416  back to the owner of the outlier points. Note everything is flipped. ---*/
17417 
17418 #ifdef HAVE_MPI
17419  /*--- We need double the number of messages to send both the conn.
17420  and the flags for the halo cells. ---*/
17421 
17422  send_req = new SU2_MPI::Request[nRecvs];
17423  recv_req = new SU2_MPI::Request[nSends];
17424 
17425  /*--- Launch the non-blocking sends of the connectivity. ---*/
17426 
17427  iMessage = 0;
17428  for (int ii=0; ii<size; ii++) {
17429  if ((ii != rank) && (nElem_Send[ii+1] > nElem_Send[ii])) {
17430  int ll = nElem_Send[ii];
17431  int kk = nElem_Send[ii+1] - nElem_Send[ii];
17432  int count = kk;
17433  int dest = ii;
17434  int tag = ii + 1;
17435  SU2_MPI::Irecv(&(idSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
17436  MPI_COMM_WORLD, &(recv_req[iMessage]));
17437  iMessage++;
17438  }
17439  }
17440 
17441  /*--- Launch the non-blocking recv's for the connectivity. ---*/
17442 
17443  iMessage = 0;
17444  for (int ii=0; ii<size; ii++) {
17445  if ((ii != rank) && (nElem_Recv[ii+1] > nElem_Recv[ii])) {
17446  int ll = nElem_Recv[ii];
17447  int kk = nElem_Recv[ii+1] - nElem_Recv[ii];
17448  int count = kk;
17449  int source = ii;
17450  int tag = rank + 1;
17451  SU2_MPI::Isend(&(idRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
17452  MPI_COMM_WORLD, &(send_req[iMessage]));
17453  iMessage++;
17454  }
17455  }
17456 #endif
17457 
17458  /*--- Copy my own rank's data into the recv buffer directly. ---*/
17459 
17460  mm = nElem_Send[rank];
17461  ll = nElem_Recv[rank];
17462  kk = nElem_Recv[rank+1];
17463 
17464  for (int nn=ll; nn<kk; nn++, mm++) idSend[mm] = idRecv[nn];
17465 
17466  /*--- Wait for the non-blocking sends and recvs to complete. ---*/
17467 
17468 #ifdef HAVE_MPI
17469  number = nRecvs;
17470  for (int ii = 0; ii < number; ii++)
17471  SU2_MPI::Waitany(number, send_req, &ind, &status);
17472 
17473  number = nSends;
17474  for (int ii = 0; ii < number; ii++)
17475  SU2_MPI::Waitany(number, recv_req, &ind, &status);
17476 
17477  delete [] send_req;
17478  delete [] recv_req;
17479 #endif
17480 
17481  /*--- Add the renumbering for the outliers to the map from before carrying
17482  the global -> renumber transformation. Note that by construction,
17483  nElem_Send[ii] == outliers.size(). We also add in the 1 for viz. here. ---*/
17484 
17485  for (int ii = 0; ii < nElem_Send[size]; ii++) {
17486  Global2Renumber[outliers[ii]] = idSend[ii] + 1;
17487  }
17488 
17489  /*--- We can now overwrite the local connectivity for our surface elems
17490  using our completed map with the new global renumbering. Whew!! Note
17491  the -1 when accessing the conn from the map. ---*/
17492 
17493  for (iElem = 0; iElem < nParallel_Line; iElem++) {
17494  iNode = (int)iElem*N_POINTS_LINE;
17495  Conn_BoundLine_Par[iNode+0] = (int)Global2Renumber[Conn_BoundLine_Par[iNode+0]-1];
17496  Conn_BoundLine_Par[iNode+1] = (int)Global2Renumber[Conn_BoundLine_Par[iNode+1]-1];
17497  }
17498 
17499  for (iElem = 0; iElem < nParallel_BoundTria; iElem++) {
17500  iNode = (int)iElem*N_POINTS_TRIANGLE;
17501  Conn_BoundTria_Par[iNode+0] = (int)Global2Renumber[Conn_BoundTria_Par[iNode+0]-1];
17502  Conn_BoundTria_Par[iNode+1] = (int)Global2Renumber[Conn_BoundTria_Par[iNode+1]-1];
17503  Conn_BoundTria_Par[iNode+2] = (int)Global2Renumber[Conn_BoundTria_Par[iNode+2]-1];
17504  }
17505 
17506  for (iElem = 0; iElem < nParallel_BoundQuad; iElem++) {
17507  iNode = (int)iElem*N_POINTS_QUADRILATERAL;
17508  Conn_BoundQuad_Par[iNode+0] = (int)Global2Renumber[Conn_BoundQuad_Par[iNode+0]-1];
17509  Conn_BoundQuad_Par[iNode+1] = (int)Global2Renumber[Conn_BoundQuad_Par[iNode+1]-1];
17510  Conn_BoundQuad_Par[iNode+2] = (int)Global2Renumber[Conn_BoundQuad_Par[iNode+2]-1];
17511  Conn_BoundQuad_Par[iNode+3] = (int)Global2Renumber[Conn_BoundQuad_Par[iNode+3]-1];
17512  }
17513 
17514  /*--- Free temporary memory ---*/
17515 
17516  delete [] idIndex;
17517  delete [] surfPoint;
17518  delete [] globalP;
17519  delete [] renumbP;
17520 
17521  delete [] idSend;
17522  delete [] idRecv;
17523  delete [] globalSend;
17524  delete [] globalRecv;
17525  delete [] renumbSend;
17526  delete [] renumbRecv;
17527  delete [] nElem_Recv;
17528  delete [] nElem_Send;
17529  delete [] nElem_Flag;
17530  delete [] Local_Halo;
17531  delete [] Buffer_Recv_nAddedPeriodic;
17532  delete [] Buffer_Send_AddedPeriodic;
17533  delete [] Buffer_Recv_AddedPeriodic;
17534  delete [] npoint_procs;
17535  delete [] starting_node;
17536  delete [] ending_node;
17537  delete [] nPoint_Linear_Elems;
17538  delete [] nPoint_Linear_Nodes;
17539  delete [] nPoint_Send;
17540  delete [] nPoint_Recv;
17541 
17542 }
17543 
17544 void COutput::WriteRestart_Parallel_ASCII(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone, unsigned short val_iInst) {
17545 
17546  /*--- Local variables ---*/
17547 
17548  unsigned short nZone = geometry->GetnZone(), nInst = config->GetnTimeInstances();
17549  unsigned short iVar;
17550  unsigned long iPoint, iExtIter = config->GetExtIter();
17551  bool fem = (config->GetKind_Solver() == FEM_ELASTICITY);
17552  bool disc_adj_fem = (config->GetKind_Solver() == DISC_ADJ_FEM);
17553  bool adjoint = (config->GetContinuous_Adjoint() ||
17554  config->GetDiscrete_Adjoint());
17555  bool dual_time = ((config->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
17556  (config->GetUnsteady_Simulation() == DT_STEPPING_2ND));
17557  ofstream restart_file;
17558  string filename;
17559 
17560  int iProcessor;
17561 
17562  /*--- Retrieve filename from config ---*/
17563 
17564  if ((config->GetContinuous_Adjoint()) || (config->GetDiscrete_Adjoint())) {
17565  filename = config->GetRestart_AdjFileName();
17566  filename = config->GetObjFunc_Extension(filename);
17567  } else if (fem) {
17568  filename = config->GetRestart_FEMFileName();
17569  } else if (disc_adj_fem){
17570  filename = config->GetRestart_AdjFEMFileName();
17571  } else {
17572  filename = config->GetRestart_FlowFileName();
17573  }
17574 
17575  /*--- Append the zone number if multizone problems ---*/
17576  if (nZone > 1)
17577  filename= config->GetMultizone_FileName(filename, val_iZone);
17578 
17579  /*--- Append the zone number if multiple instance problems ---*/
17580  if (nInst > 1)
17581  filename= config->GetMultiInstance_FileName(filename, val_iInst);
17582 
17583  /*--- Unsteady problems require an iteration number to be appended. ---*/
17584  if (config->GetUnsteady_Simulation() == HARMONIC_BALANCE) {
17585  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(val_iInst));
17586  } else if (config->GetWrt_Unsteady()) {
17587  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(iExtIter));
17588  } else if ((fem || disc_adj_fem) && (config->GetWrt_Dynamic())) {
17589  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(iExtIter));
17590  }
17591 
17592  /*--- Only the master node writes the header. ---*/
17593 
17594  if (rank == MASTER_NODE) {
17595  restart_file.open(filename.c_str(), ios::out);
17596  restart_file.precision(15);
17597  restart_file << "\"PointID\"";
17598  for (iVar = 0; iVar < Variable_Names.size()-1; iVar++)
17599  restart_file << "\t\"" << Variable_Names[iVar] << "\"";
17600  restart_file << "\t\"" << Variable_Names[Variable_Names.size()-1] << "\"" << endl;
17601  restart_file.close();
17602  }
17603 
17604 #ifdef HAVE_MPI
17606 #endif
17607 
17608  /*--- All processors open the file. ---*/
17609 
17610  restart_file.open(filename.c_str(), ios::out | ios::app);
17611  restart_file.precision(15);
17612 
17613  /*--- Write the restart file in parallel, processor by processor. ---*/
17614 
17615  unsigned long myPoint = 0, offset = 0, Global_Index;
17616  for (iProcessor = 0; iProcessor < size; iProcessor++) {
17617  if (rank == iProcessor) {
17618  for (iPoint = 0; iPoint < nParallel_Poin; iPoint++) {
17619 
17620  /*--- Global Index of the current point. (note outer loop over procs) ---*/
17621 
17622  Global_Index = iPoint + offset;
17623 
17624  /*--- Only write original domain points, i.e., exclude any periodic
17625  or halo nodes, even if they are output in the viz. files. ---*/
17626 
17627  if (Global_Index < nPoint_Restart) {
17628 
17629  /*--- Write global index. (note outer loop over procs) ---*/
17630 
17631  restart_file << Global_Index << "\t";
17632  myPoint++;
17633 
17634  /*--- Loop over the variables and write the values to file ---*/
17635 
17636  for (iVar = 0; iVar < nVar_Par; iVar++) {
17637  restart_file << scientific << Parallel_Data[iVar][iPoint] << "\t";
17638  }
17639  restart_file << "\n";
17640  }
17641  }
17642  }
17643  /*--- Flush the file and wait for all processors to arrive. ---*/
17644  restart_file.flush();
17645 #ifdef HAVE_MPI
17648 #endif
17649 
17650  }
17651 
17652  /*--- Write the metadata (master rank alone) ----*/
17653 
17654  if (rank == MASTER_NODE) {
17655  if (dual_time)
17656  restart_file <<"EXT_ITER= " << config->GetExtIter() + 1 << endl;
17657  else
17658  restart_file <<"EXT_ITER= " << config->GetExtIter() + config->GetExtIter_OffSet() + 1 << endl;
17659  restart_file <<"AOA= " << config->GetAoA() - config->GetAoA_Offset() << endl;
17660  restart_file <<"SIDESLIP_ANGLE= " << config->GetAoS() - config->GetAoS_Offset() << endl;
17661  restart_file <<"INITIAL_BCTHRUST= " << config->GetInitial_BCThrust() << endl;
17662  restart_file <<"DCD_DCL_VALUE= " << config->GetdCD_dCL() << endl;
17663  restart_file <<"DCMX_DCL_VALUE= " << config->GetdCMx_dCL() << endl;
17664  restart_file <<"DCMY_DCL_VALUE= " << config->GetdCMy_dCL() << endl;
17665  restart_file <<"DCMZ_DCL_VALUE= " << config->GetdCMz_dCL() << endl;
17666  if (adjoint) restart_file << "SENS_AOA=" << solver[ADJFLOW_SOL]->GetTotal_Sens_AoA() * PI_NUMBER / 180.0 << endl;
17667  }
17668 
17669  /*--- All processors close the file. ---*/
17670 
17671  restart_file.close();
17672 
17673 }
17674 
17675 void COutput::WriteRestart_Parallel_Binary(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone, unsigned short val_iInst) {
17676 
17677  /*--- Local variables ---*/
17678 
17679  unsigned short iVar, nZone = geometry->GetnZone(), nInst = config->GetnTimeInstances();
17680  unsigned long iPoint, iExtIter = config->GetExtIter();
17681  bool fem = (config->GetKind_Solver() == FEM_ELASTICITY);
17682  bool adjoint = (config->GetContinuous_Adjoint() ||
17683  config->GetDiscrete_Adjoint());
17684  bool dual_time = ((config->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
17685  (config->GetUnsteady_Simulation() == DT_STEPPING_2ND));
17686  bool wrt_perf = config->GetWrt_Performance();
17687  ofstream restart_file;
17688  string filename;
17689  char str_buf[CGNS_STRING_SIZE], fname[100];
17690  su2double file_size = 0.0, StartTime, StopTime, UsedTime, Bandwidth;
17691 
17692  /*--- Retrieve filename from config ---*/
17693 
17694  if ((config->GetContinuous_Adjoint()) || (config->GetDiscrete_Adjoint())) {
17695  filename = config->GetRestart_AdjFileName();
17696  filename = config->GetObjFunc_Extension(filename);
17697  } else if (fem) {
17698  filename = config->GetRestart_FEMFileName();
17699  } else {
17700  filename = config->GetRestart_FlowFileName();
17701  }
17702 
17703  /*--- Append the zone number if multizone problems ---*/
17704  if (nZone > 1)
17705  filename= config->GetMultizone_FileName(filename, val_iZone);
17706 
17707  /*--- Append the zone number if multiple instance problems ---*/
17708  if (nInst > 1)
17709  filename= config->GetMultiInstance_FileName(filename, val_iInst);
17710 
17711  /*--- Unsteady problems require an iteration number to be appended. ---*/
17712  if (config->GetUnsteady_Simulation() == HARMONIC_BALANCE) {
17713  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(val_iInst));
17714  } else if (config->GetWrt_Unsteady()) {
17715  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(iExtIter));
17716  } else if ((fem) && (config->GetWrt_Dynamic())) {
17717  filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(iExtIter));
17718  }
17719 
17720  strcpy(fname, filename.c_str());
17721 
17722  /*--- Prepare the first ints containing the counts. The first is a
17723  magic number that we can use to check for binary files (it is the hex
17724  representation for "SU2"). The second two values are number of variables
17725  and number of points (DoFs). The last two values are for metadata:
17726  one int for ExtIter and 8 su2doubles. ---*/
17727 
17728  int var_buf_size = 5;
17729  int var_buf[5] = {535532, nVar_Par, (int)nGlobalPoint_Sort, 1, 8};
17730 
17731  /*--- Prepare the 1D data buffer on this rank. ---*/
17732 
17733  passivedouble *buf = new passivedouble[nParallel_Poin*nVar_Par];
17734 
17735  /*--- For now, create a temp 1D buffer to load up the data for writing.
17736  This will be replaced with a derived data type most likely. ---*/
17737 
17738  for (iPoint = 0; iPoint < nParallel_Poin; iPoint++)
17739  for (iVar = 0; iVar < nVar_Par; iVar++)
17740  buf[iPoint*nVar_Par+iVar] = SU2_TYPE::GetValue(Parallel_Data[iVar][iPoint]);
17741 
17742  /*--- Prepare metadata. ---*/
17743 
17744  int Restart_ExtIter;
17745  if (dual_time)
17746  Restart_ExtIter= (int)config->GetExtIter() + 1;
17747  else
17748  Restart_ExtIter = (int)config->GetExtIter() + (int)config->GetExtIter_OffSet() + 1;
17749 
17750  passivedouble Restart_Metadata[8] = {
17751  SU2_TYPE::GetValue(config->GetAoA() - config->GetAoA_Offset()),
17752  SU2_TYPE::GetValue(config->GetAoS() - config->GetAoS_Offset()),
17754  SU2_TYPE::GetValue(config->GetdCD_dCL()),
17755  SU2_TYPE::GetValue(config->GetdCMx_dCL()),
17756  SU2_TYPE::GetValue(config->GetdCMy_dCL()),
17757  SU2_TYPE::GetValue(config->GetdCMz_dCL()),
17758  0.0
17759  };
17760 
17761  if (adjoint) Restart_Metadata[4] = SU2_TYPE::GetValue(solver[ADJFLOW_SOL]->GetTotal_Sens_AoA() * PI_NUMBER / 180.0);
17762 
17763  /*--- Set a timer for the binary file writing. ---*/
17764 
17765 #ifndef HAVE_MPI
17766  StartTime = su2double(clock())/su2double(CLOCKS_PER_SEC);
17767 #else
17768  StartTime = MPI_Wtime();
17769 #endif
17770 
17771 #ifndef HAVE_MPI
17772 
17773  FILE* fhw;
17774  fhw = fopen(fname, "wb");
17775 
17776  /*--- Error check for opening the file. ---*/
17777 
17778  if (!fhw) {
17779  SU2_MPI::Error(string("Unable to open SU2 restart file ") + string(fname), CURRENT_FUNCTION);
17780  }
17781 
17782  /*--- First, write the number of variables and points. ---*/
17783 
17784  fwrite(var_buf, var_buf_size, sizeof(int), fhw);
17785  file_size += (su2double)var_buf_size*sizeof(int);
17786 
17787  /*--- Write the variable names to the file. Note that we are adopting a
17788  fixed length of 33 for the string length to match with CGNS. This is
17789  needed for when we read the strings later. ---*/
17790 
17791  for (iVar = 0; iVar < nVar_Par; iVar++) {
17792  strncpy(str_buf, Variable_Names[iVar].c_str(), CGNS_STRING_SIZE);
17793  fwrite(str_buf, CGNS_STRING_SIZE, sizeof(char), fhw);
17794  file_size += (su2double)CGNS_STRING_SIZE*sizeof(char);
17795  }
17796 
17797  /*--- Call to write the entire restart file data in binary in one shot. ---*/
17798 
17799  fwrite(buf, nVar_Par*nParallel_Poin, sizeof(passivedouble), fhw);
17800  file_size += (su2double)nVar_Par*nParallel_Poin*sizeof(passivedouble);
17801 
17802  /*--- Write the external iteration. ---*/
17803 
17804  fwrite(&Restart_ExtIter, 1, sizeof(int), fhw);
17805  file_size += (su2double)sizeof(int);
17806 
17807  /*--- Write the metadata. ---*/
17808 
17809  fwrite(Restart_Metadata, 8, sizeof(passivedouble), fhw);
17810  file_size += (su2double)8*sizeof(passivedouble);
17811 
17812  /*--- Close the file. ---*/
17813 
17814  fclose(fhw);
17815 
17816 #else
17817 
17818  /*--- Parallel binary output using MPI I/O. ---*/
17819 
17820  MPI_File fhw;
17821  SU2_MPI::Status status;
17822  MPI_Datatype etype, filetype;
17823  MPI_Offset disp;
17824  int ierr;
17825 
17826  /*--- We're writing only su2doubles in the data portion of the file. ---*/
17827 
17828  etype = MPI_DOUBLE;
17829 
17830  /*--- Define a derived datatype for this ranks contiguous chunk of data
17831  that will be placed in the restart (1D array size = num points * num vars). ---*/
17832 
17833  MPI_Type_contiguous(nVar_Par*nParallel_Poin, MPI_DOUBLE, &filetype);
17834  MPI_Type_commit(&filetype);
17835 
17836  /*--- All ranks open the file using MPI. Here, we try to open the file with
17837  exclusive so that an error is generated if the file exists. We always want
17838  to write a fresh restart file, so we delete any existing files and create
17839  a new one. ---*/
17840 
17841  ierr = MPI_File_open(MPI_COMM_WORLD, fname,
17842  MPI_MODE_CREATE|MPI_MODE_EXCL|MPI_MODE_WRONLY,
17843  MPI_INFO_NULL, &fhw);
17844  if (ierr != MPI_SUCCESS) {
17845  MPI_File_close(&fhw);
17846  if (rank == 0)
17847  MPI_File_delete(fname, MPI_INFO_NULL);
17848  ierr = MPI_File_open(MPI_COMM_WORLD, fname,
17849  MPI_MODE_CREATE|MPI_MODE_EXCL|MPI_MODE_WRONLY,
17850  MPI_INFO_NULL, &fhw);
17851  }
17852 
17853  /*--- Error check opening the file. ---*/
17854 
17855  if (ierr) {
17856  SU2_MPI::Error(string("Unable to open SU2 restart file ") + string(fname), CURRENT_FUNCTION);
17857  }
17858 
17859  /*--- First, write the number of variables and points (i.e., cols and rows),
17860  which we will need in order to read the file later. Also, write the
17861  variable string names here. Only the master rank writes the header. ---*/
17862 
17863  if (rank == MASTER_NODE) {
17864  MPI_File_write(fhw, var_buf, var_buf_size, MPI_INT, MPI_STATUS_IGNORE);
17865  file_size += (su2double)var_buf_size*sizeof(int);
17866 
17867  /*--- Write the variable names to the file. Note that we are adopting a
17868  fixed length of 33 for the string length to match with CGNS. This is
17869  needed for when we read the strings later. ---*/
17870 
17871  for (iVar = 0; iVar < nVar_Par; iVar++) {
17872  disp = var_buf_size*sizeof(int) + iVar*CGNS_STRING_SIZE*sizeof(char);
17873  strcpy(str_buf, Variable_Names[iVar].c_str());
17874  MPI_File_write_at(fhw, disp, str_buf, CGNS_STRING_SIZE, MPI_CHAR, MPI_STATUS_IGNORE);
17875  file_size += (su2double)CGNS_STRING_SIZE*sizeof(char);
17876  }
17877  }
17878 
17879  /*--- Compute the offset for this rank's linear partition of the data in bytes.
17880  After the calculations above, we have the partition sizes store in nPoint_Linear
17881  in cumulative storage format. ---*/
17882 
17883  disp = (var_buf_size*sizeof(int) + nVar_Par*CGNS_STRING_SIZE*sizeof(char) +
17884  nVar_Par*nPoint_Cum[rank]*sizeof(passivedouble));
17885 
17886  /*--- Set the view for the MPI file write, i.e., describe the location in
17887  the file that this rank "sees" for writing its piece of the restart file. ---*/
17888 
17889  MPI_File_set_view(fhw, disp, etype, filetype, (char*)"native", MPI_INFO_NULL);
17890 
17891  /*--- Collective call for all ranks to write to their view simultaneously. ---*/
17892 
17893  MPI_File_write_all(fhw, buf, nVar_Par*nParallel_Poin, MPI_DOUBLE, &status);
17894  file_size += (su2double)nVar_Par*nParallel_Poin*sizeof(passivedouble);
17895 
17896  /*--- Free the derived datatype. ---*/
17897 
17898  MPI_Type_free(&filetype);
17899 
17900  /*--- Reset the file view before writing the metadata. ---*/
17901 
17902  MPI_File_set_view(fhw, 0, MPI_BYTE, MPI_BYTE, (char*)"native", MPI_INFO_NULL);
17903 
17904  /*--- Finally, the master rank writes the metadata. ---*/
17905 
17906  if (rank == MASTER_NODE) {
17907 
17908  /*--- External iteration. ---*/
17909 
17910  disp = (var_buf_size*sizeof(int) + nVar_Par*CGNS_STRING_SIZE*sizeof(char) +
17911  nVar_Par*nGlobalPoint_Sort*sizeof(passivedouble));
17912  MPI_File_write_at(fhw, disp, &Restart_ExtIter, 1, MPI_INT, MPI_STATUS_IGNORE);
17913  file_size += (su2double)sizeof(int);
17914 
17915  /*--- Additional doubles for AoA, AoS, etc. ---*/
17916 
17917  disp = (var_buf_size*sizeof(int) + nVar_Par*CGNS_STRING_SIZE*sizeof(char) +
17918  nVar_Par*nGlobalPoint_Sort*sizeof(passivedouble) + 1*sizeof(int));
17919  MPI_File_write_at(fhw, disp, Restart_Metadata, 8, MPI_DOUBLE, MPI_STATUS_IGNORE);
17920  file_size += (su2double)8*sizeof(passivedouble);
17921 
17922  }
17923 
17924  /*--- All ranks close the file after writing. ---*/
17925 
17926  MPI_File_close(&fhw);
17927 
17928 #endif
17929 
17930  /*--- Compute and store the write time. ---*/
17931 
17932 #ifndef HAVE_MPI
17933  StopTime = su2double(clock())/su2double(CLOCKS_PER_SEC);
17934 #else
17935  StopTime = MPI_Wtime();
17936 #endif
17937  UsedTime = StopTime-StartTime;
17938 
17939  /*--- Communicate the total file size for the restart ---*/
17940 
17941 #ifdef HAVE_MPI
17942  su2double my_file_size = file_size;
17943  SU2_MPI::Allreduce(&my_file_size, &file_size, 1,
17945 #endif
17946 
17947  /*--- Compute and store the bandwidth ---*/
17948 
17949  Bandwidth = file_size/(1.0e6)/UsedTime;
17950  config->SetRestart_Bandwidth_Agg(config->GetRestart_Bandwidth_Agg()+Bandwidth);
17951 
17952  if ((rank == MASTER_NODE) && (wrt_perf)) {
17953  cout << "Wrote " << file_size/1.0e6 << " MB to disk in ";
17954  cout << UsedTime << " s. (" << Bandwidth << " MB/s)." << endl;
17955  }
17956 
17957  /*--- Free temporary data buffer for writing the binary file. ---*/
17958 
17959  delete [] buf;
17960 
17961 }
17962 
17964  CSolver *FlowSolver, unsigned long iExtIter,
17965  unsigned short val_iZone, unsigned short val_direction) {
17966 
17967  /*--- This routine is for exporting slices of field data for 2D cartesian
17968  grids. It assumes that the grid points lie on lines of constant x-
17969  or y-coordinates. It is a simple way to export slices or profiles on
17970  these meshes for use in verification and validation work. It will
17971  eventually be replaced by general routines for probing/slicing. ---*/
17972 
17973  int DIRECTION = (int)val_direction;
17974 
17975  su2double coordMin, coordMax;
17976  coordMin = config->GetStations_Bounds(0);
17977  coordMax = config->GetStations_Bounds(1);
17978 
17979  unsigned short iVar;
17980  unsigned long iPoint, iVertex, Global_Index;
17981  char cstr[200];
17982 
17983  int rank = MASTER_NODE, iProcessor, nProcessor = SINGLE_NODE;
17984 #ifdef HAVE_MPI
17985  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
17986  MPI_Comm_size(MPI_COMM_WORLD, &nProcessor);
17987 #endif
17988 
17989  bool isPeriodic;
17990 
17991  int *Local_Halo = new int[geometry->GetnPoint()];
17992  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
17993  Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain();
17994 
17995  for (unsigned short iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
17996  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
17997 
17998  /*--- Checking for less than or equal to the rank, because there may
17999  be some periodic halo nodes that send info to the same rank. ---*/
18000 
18001  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
18002  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
18003  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
18004  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
18005  if (isPeriodic) Local_Halo[iPoint] = false;
18006  }
18007  }
18008  }
18009 
18010  /*--- Sum total number of nodes that belong to the domain ---*/
18011 
18012  unsigned long nTotalPoint;
18013  unsigned long nLocalPoint = 0;
18014  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
18015  if (Local_Halo[iPoint] == false)
18016  nLocalPoint++;
18017 
18018 #ifdef HAVE_MPI
18019  SU2_MPI::Allreduce(&nLocalPoint, &nTotalPoint, 1,
18021 #else
18022  nTotalPoint = nLocalPoint;
18023 #endif
18024 
18025  unsigned long *npoint_procs = new unsigned long[nProcessor];
18026  unsigned long *nPoint_Linear = new unsigned long[nProcessor+1];
18027 
18028  unsigned long total_pt_accounted = 0;
18029  for (int ii = 0; ii < nProcessor; ii++) {
18030  npoint_procs[ii] = nTotalPoint/nProcessor;
18031  total_pt_accounted = total_pt_accounted + npoint_procs[ii];
18032  }
18033 
18034  /*--- Get the number of remainder points after the even division. ---*/
18035 
18036  unsigned long rem_points = nTotalPoint-total_pt_accounted;
18037  for (unsigned long ii = 0; ii < rem_points; ii++) {
18038  npoint_procs[ii]++;
18039  }
18040 
18041  /*--- Store the point offsets for each rank. ---*/
18042 
18043  nPoint_Linear[0] = 0;
18044  for (int ii = 1; ii < nProcessor; ii++) {
18045  nPoint_Linear[ii] = nPoint_Linear[ii-1] + npoint_procs[ii-1];
18046  }
18047  nPoint_Linear[nProcessor] = nTotalPoint;
18048 
18049  unsigned long Buffer_Send_nVertex[1], *Buffer_Recv_nVertex = NULL;
18050  unsigned long nLocalVertex_Surface = 0;
18051  unsigned long MaxLocalVertex_Surface = 0;
18052 
18053  /*--- Find the max number of vertices we will send from among all
18054  partitions and set up buffers. The master node will handle the
18055  writing of the CSV file after gathering all of the data. ---*/
18056 
18057  nLocalVertex_Surface = 0;
18058  for (iPoint = 0; iPoint < nParallel_Poin; iPoint++) {
18059 
18060  /*--- Global Index of the current point. (note outer loop over procs) ---*/
18061 
18062  Global_Index = iPoint + nPoint_Linear[rank];
18063 
18064  /*--- Only write original domain points, i.e., exclude any periodic
18065  or halo nodes, even if they are output in the viz. files. ---*/
18066 
18067  if (Global_Index < geometry->GetGlobal_nPointDomain()) {
18068  if ((Parallel_Data[DIRECTION][iPoint] > coordMin) &&
18069  (Parallel_Data[DIRECTION][iPoint] < coordMax)) {
18070  nLocalVertex_Surface++;
18071  }
18072  }
18073  }
18074 
18075  /*--- Communicate the number of local vertices on each partition
18076  to the master node ---*/
18077 
18078  Buffer_Send_nVertex[0] = nLocalVertex_Surface;
18079  if (rank == MASTER_NODE) Buffer_Recv_nVertex = new unsigned long [nProcessor];
18080 
18081 #ifdef HAVE_MPI
18082  SU2_MPI::Allreduce(&nLocalVertex_Surface, &MaxLocalVertex_Surface, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
18083  SU2_MPI::Gather(&Buffer_Send_nVertex, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nVertex, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
18084 #else
18085  MaxLocalVertex_Surface = nLocalVertex_Surface;
18086  Buffer_Recv_nVertex[0] = Buffer_Send_nVertex[0];
18087 #endif
18088 
18089  /*--- Send and Recv buffers ---*/
18090 
18091  su2double *Buffer_Send_Data = new su2double [MaxLocalVertex_Surface*nVar_Par];
18092  su2double *Buffer_Recv_Data = NULL;
18093 
18094  unsigned long *Buffer_Send_GlobalIndex = new unsigned long [MaxLocalVertex_Surface];
18095  unsigned long *Buffer_Recv_GlobalIndex = NULL;
18096 
18097  /*--- Prepare the receive buffers on the master node only. ---*/
18098 
18099  if (rank == MASTER_NODE) {
18100  Buffer_Recv_Data = new su2double [nProcessor*MaxLocalVertex_Surface*nVar_Par];
18101  Buffer_Recv_GlobalIndex = new unsigned long [nProcessor*MaxLocalVertex_Surface];
18102  }
18103 
18104  /*--- Loop over all vertices in this partition and load the
18105  data of the specified type into the buffer to be sent to
18106  the master node. ---*/
18107 
18108  nLocalVertex_Surface = 0;
18109  for (iPoint = 0; iPoint < nParallel_Poin; iPoint++) {
18110 
18111  /*--- Global Index of the current point. (note outer loop over procs) ---*/
18112 
18113  Global_Index = iPoint + nPoint_Linear[rank];
18114 
18115  /*--- Only write original domain points, i.e., exclude any periodic
18116  or halo nodes, even if they are output in the viz. files. ---*/
18117 
18118  if (Global_Index < geometry->GetGlobal_nPointDomain()) {
18119  if ((Parallel_Data[DIRECTION][iPoint] > coordMin) &&
18120  (Parallel_Data[DIRECTION][iPoint] < coordMax)) {
18121  Buffer_Send_GlobalIndex[nLocalVertex_Surface] = Global_Index;
18122  for (iVar = 0; iVar < nVar_Par; iVar++) {
18123  Buffer_Send_Data[nLocalVertex_Surface*nVar_Par+iVar] = Parallel_Data[iVar][iPoint];
18124  }
18125  nLocalVertex_Surface++;
18126  }
18127  }
18128  }
18129 
18130  /*--- Send the information to the master node ---*/
18131 
18132 #ifdef HAVE_MPI
18133  SU2_MPI::Gather(Buffer_Send_Data, MaxLocalVertex_Surface*nVar_Par, MPI_DOUBLE, Buffer_Recv_Data, MaxLocalVertex_Surface*nVar_Par, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
18134  SU2_MPI::Gather(Buffer_Send_GlobalIndex, MaxLocalVertex_Surface, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, MaxLocalVertex_Surface, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
18135 #else
18136  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[0]; iVertex++) {
18137  Buffer_Recv_GlobalIndex[iVertex] = Buffer_Send_GlobalIndex[iVertex];
18138  for (iVar = 0; iVar < nVar_Par; iVar++) {
18139  Buffer_Recv_Data[iVertex*nVar_Par+iVar] = Buffer_Send_Data[iVertex*nVar_Par+iVar];
18140  }
18141  }
18142 #endif
18143 
18144  /*--- The master node unpacks the data and writes the surface CSV file ---*/
18145 
18146  if (rank == MASTER_NODE) {
18147 
18148  /*--- Write file name with extension if unsteady ---*/
18149  char buffer[50];
18150  string filename = "slice";
18151  if (DIRECTION == 0) {
18152  SPRINTF (buffer, "_vert.csv");
18153  } else if (DIRECTION == 1) {
18154  SPRINTF (buffer, "_hori.csv");
18155  }
18156  ofstream SurfFlow_file;
18157 
18158  /*--- Write file name with extension if unsteady ---*/
18159  strcpy (cstr, filename.c_str());
18160  strcat (cstr, buffer);
18161  SurfFlow_file.precision(15);
18162  SurfFlow_file.open(cstr, ios::out);
18163 
18164  /*--- Global index is first, then the rest of the data. We already have the names. ---*/
18165 
18166  SurfFlow_file << "\"Global_Index\",";
18167  for (iVar = 0; iVar < Variable_Names.size()-1; iVar++) {
18168  SurfFlow_file << "\"" << Variable_Names[iVar] << "\",";
18169  }
18170  SurfFlow_file << "\"" << Variable_Names[Variable_Names.size()-1] << "\"" << endl;
18171 
18172  /*--- Loop through all of the collected data and write each node's values ---*/
18173 
18174  unsigned long Total_Index;
18175  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
18176  for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) {
18177 
18178  /*--- Current index position and global index ---*/
18179 
18180  Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex;
18181  Global_Index = Buffer_Recv_GlobalIndex[Total_Index];
18182 
18183  /*--- Write the the data ---*/
18184 
18185  SurfFlow_file << scientific << Global_Index;
18186  Total_Index = iProcessor*MaxLocalVertex_Surface*nVar_Par+iVertex*nVar_Par;
18187  for (iVar = 0; iVar < nVar_Par; iVar++) {
18188  SurfFlow_file << scientific << ", " << Buffer_Recv_Data[Total_Index+iVar];
18189  }
18190  SurfFlow_file << endl;
18191 
18192  }
18193  }
18194 
18195  /*--- Close the CSV file ---*/
18196 
18197  SurfFlow_file.close();
18198 
18199  /*--- Release the recv buffers on the master node ---*/
18200 
18201  delete [] Buffer_Recv_Data;
18202  delete [] Buffer_Recv_GlobalIndex;
18203  delete [] Buffer_Recv_nVertex;
18204 
18205  }
18206 
18207  /*--- Release the memory for the remaining buffers and exit ---*/
18208 
18209  delete [] Buffer_Send_Data;
18210  delete [] Buffer_Send_GlobalIndex;
18211 
18212 }
18213 
18214 void COutput::DeallocateConnectivity_Parallel(CConfig *config, CGeometry *geometry, bool surf_sol) {
18215 
18216  /*--- Deallocate memory for connectivity data on each processor. ---*/
18217 
18218  if (surf_sol) {
18219  if (nParallel_Line > 0 && Conn_BoundLine_Par != NULL)
18220  delete [] Conn_BoundLine_Par;
18221  if (nParallel_BoundTria > 0 && Conn_BoundTria_Par != NULL)
18222  delete [] Conn_BoundTria_Par;
18223  if (nParallel_BoundQuad > 0 && Conn_BoundQuad_Par != NULL)
18224  delete [] Conn_BoundQuad_Par;
18225  }
18226  else {
18227  if (nParallel_Tria > 0 && Conn_Tria_Par != NULL) delete [] Conn_Tria_Par;
18228  if (nParallel_Quad > 0 && Conn_Quad_Par != NULL) delete [] Conn_Quad_Par;
18229  if (nParallel_Tetr > 0 && Conn_Tetr_Par != NULL) delete [] Conn_Tetr_Par;
18230  if (nParallel_Hexa > 0 && Conn_Hexa_Par != NULL) delete [] Conn_Hexa_Par;
18231  if (nParallel_Pris > 0 && Conn_Pris_Par != NULL) delete [] Conn_Pris_Par;
18232  if (nParallel_Pyra > 0 && Conn_Pyra_Par != NULL) delete [] Conn_Pyra_Par;
18233  }
18234 
18235 }
18236 
18238 
18239  /*--- Deallocate memory for solution data ---*/
18240 
18241  for (unsigned short iVar = 0; iVar < nVar_Par; iVar++) {
18242  if (Parallel_Data[iVar] != NULL) delete [] Parallel_Data[iVar];
18243  }
18244  if (Parallel_Data != NULL) delete [] Parallel_Data;
18245 
18246  /*--- Deallocate the structures holding the linear partitioning ---*/
18247 
18248  if (Local_Halo_Sort != NULL) delete [] Local_Halo_Sort;
18249 
18250  if (beg_node != NULL) delete [] beg_node;
18251  if (end_node != NULL) delete [] end_node;
18252 
18253  if (nPoint_Lin != NULL) delete [] nPoint_Lin;
18254  if (nPoint_Cum != NULL) delete [] nPoint_Cum;
18255 
18256 }
18257 
18259 
18260  /*--- Deallocate memory for surface solution data ---*/
18261 
18262  for (unsigned short iVar = 0; iVar < nVar_Par; iVar++) {
18263  if (Parallel_Surf_Data[iVar] != NULL) delete [] Parallel_Surf_Data[iVar];
18264  }
18265  if (Parallel_Surf_Data != NULL) delete [] Parallel_Surf_Data;
18266 
18267 }
18268 
18270 
18271  /*--- Local variables needed on all processors ---*/
18272 
18273  unsigned short iDim, nDim = geometry->GetnDim();
18274  unsigned long iPoint, jPoint, kPoint;
18275 
18276  int iProcessor, nProcessor = size;
18277 
18278  unsigned long iVertex, iMarker;
18279  unsigned long Buffer_Send_nPoin[1], *Buffer_Recv_nPoin = NULL;
18280  unsigned long nLocalPoint = 0, MaxLocalPoint = 0;
18281 
18282  unsigned long index, iChar;
18283 
18284  char str_buf[MAX_STRING_SIZE];
18285  vector<string> Marker_Tags;
18286  vector<string>::iterator it;
18287 
18288  unsigned long *nRowCum_Counter = NULL;
18289 
18290  if (rank == MASTER_NODE) Buffer_Recv_nPoin = new unsigned long[nProcessor];
18291 
18292  /*--- Search all boundaries on the present rank to count the number
18293  of nodes found on inlet markers. ---*/
18294 
18295  nLocalPoint = 0;
18296  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
18297  if (config->GetMarker_All_KindBC(iMarker) == INLET_FLOW) {
18298  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
18299  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
18300 
18301  /*--- Only communicate owned nodes to avoid duplicates. ---*/
18302 
18303  if (geometry->node[iPoint]->GetDomain())
18304  nLocalPoint++;
18305 
18306  }
18307  }
18308  }
18309  Buffer_Send_nPoin[0] = nLocalPoint;
18310 
18311  /*--- Communicate the total number of nodes on this domain. ---*/
18312 
18313 #ifdef HAVE_MPI
18314  SU2_MPI::Gather(&Buffer_Send_nPoin, 1, MPI_UNSIGNED_LONG,
18315  Buffer_Recv_nPoin, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
18316  SU2_MPI::Allreduce(&nLocalPoint, &MaxLocalPoint, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
18317 #else
18318  Buffer_Recv_nPoin[0] = Buffer_Send_nPoin[0];
18319  MaxLocalPoint = nLocalPoint;
18320 #endif
18321 
18322  /*--- Send and Recv buffers. ---*/
18323 
18324  su2double *Buffer_Send_X = new su2double[MaxLocalPoint];
18325  su2double *Buffer_Recv_X = NULL;
18326 
18327  su2double *Buffer_Send_Y = new su2double[MaxLocalPoint];
18328  su2double *Buffer_Recv_Y = NULL;
18329 
18330  su2double *Buffer_Send_Z = NULL, *Buffer_Recv_Z = NULL;
18331  if (nDim == 3) Buffer_Send_Z = new su2double[MaxLocalPoint];
18332 
18333  char *Buffer_Send_Str = new char[MaxLocalPoint*MAX_STRING_SIZE];
18334  char *Buffer_Recv_Str = NULL;
18335 
18336  /*--- Prepare the receive buffers in the master node only. ---*/
18337 
18338  if (rank == MASTER_NODE) {
18339 
18340  Buffer_Recv_X = new su2double[nProcessor*MaxLocalPoint];
18341  Buffer_Recv_Y = new su2double[nProcessor*MaxLocalPoint];
18342  if (nDim == 3) Buffer_Recv_Z = new su2double[nProcessor*MaxLocalPoint];
18343  Buffer_Recv_Str = new char[nProcessor*MaxLocalPoint*MAX_STRING_SIZE];
18344 
18345  /*--- Sum total number of nodes to be written and allocate arrays ---*/
18346 
18347  unsigned long nGlobal_InletPoint = 0;
18348  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
18349  nGlobal_InletPoint += Buffer_Recv_nPoin[iProcessor];
18350  }
18351  InletCoords = new su2double*[nDim];
18352  for (iDim = 0; iDim < nDim; iDim++) {
18353  InletCoords[iDim] = new su2double[nGlobal_InletPoint];
18354  }
18355  }
18356 
18357  /*--- Main communication routine. Loop over each coordinate and perform
18358  the MPI comm. Temporary 1-D buffers are used to send the coordinates at
18359  all nodes on each partition to the master node. These are then unpacked
18360  by the master and sorted by marker tag in one large n-dim. array. ---*/
18361 
18362  /*--- Loop over this partition to collect the coords of the local points. ---*/
18363 
18364  su2double *Coords_Local; jPoint = 0;
18365  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
18366  if (config->GetMarker_All_KindBC(iMarker) == INLET_FLOW) {
18367 
18368  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
18369  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
18370 
18371  /*--- Only communicate owned nodes to avoid duplicates. ---*/
18372 
18373  if (geometry->node[iPoint]->GetDomain()) {
18374 
18375  /*--- Retrieve local coordinates at this node. ---*/
18376 
18377  Coords_Local = geometry->node[iPoint]->GetCoord();
18378 
18379  /*--- Load local coords into the temporary send buffer. ---*/
18380 
18381  Buffer_Send_X[jPoint] = Coords_Local[0];
18382  Buffer_Send_Y[jPoint] = Coords_Local[1];
18383  if (nDim == 3) Buffer_Send_Z[jPoint] = Coords_Local[2];
18384 
18385  /*--- If US system, the output should be in inches ---*/
18386 
18387  if (config->GetSystemMeasurements() == US) {
18388  Buffer_Send_X[jPoint] *= 12.0;
18389  Buffer_Send_Y[jPoint] *= 12.0;
18390  if (nDim == 3) Buffer_Send_Z[jPoint] *= 12.0;
18391  }
18392 
18393  /*--- Store the marker tag for this particular node. ---*/
18394 
18395  SPRINTF(&Buffer_Send_Str[jPoint*MAX_STRING_SIZE], "%s",
18396  config->GetMarker_All_TagBound(iMarker).c_str());
18397 
18398  /*--- Increment jPoint as the counter. We need this because iPoint
18399  may include halo nodes that we skip over during this loop. ---*/
18400 
18401  jPoint++;
18402 
18403  }
18404  }
18405  }
18406  }
18407 
18408  /*--- Gather the coordinate data on the master node using MPI. ---*/
18409 
18410 #ifdef HAVE_MPI
18411  SU2_MPI::Gather(Buffer_Send_X, MaxLocalPoint, MPI_DOUBLE, Buffer_Recv_X, MaxLocalPoint, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
18412  SU2_MPI::Gather(Buffer_Send_Y, MaxLocalPoint, MPI_DOUBLE, Buffer_Recv_Y, MaxLocalPoint, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
18413  if (nDim == 3) {
18414  SU2_MPI::Gather(Buffer_Send_Z, MaxLocalPoint, MPI_DOUBLE, Buffer_Recv_Z, MaxLocalPoint, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
18415  }
18416  SU2_MPI::Gather(Buffer_Send_Str, MaxLocalPoint*MAX_STRING_SIZE, MPI_CHAR, Buffer_Recv_Str, MaxLocalPoint*MAX_STRING_SIZE, MPI_CHAR, MASTER_NODE, MPI_COMM_WORLD);
18417 #else
18418  for (iPoint = 0; iPoint < MaxLocalPoint; iPoint++) {
18419  Buffer_Recv_X[iPoint] = Buffer_Send_X[iPoint];
18420  Buffer_Recv_Y[iPoint] = Buffer_Send_Y[iPoint];
18421  if (nDim == 3) Buffer_Recv_Z[iPoint] = Buffer_Send_Z[iPoint];
18422  index = iPoint*MAX_STRING_SIZE;
18423  for (iChar = 0; iChar < MAX_STRING_SIZE; iChar++) {
18424  Buffer_Recv_Str[index + iChar] = Buffer_Send_Str[index + iChar];
18425  }
18426  }
18427 #endif
18428 
18429  /*--- The master node unpacks and sorts this variable by marker tag. ---*/
18430 
18431  if (rank == MASTER_NODE) {
18432 
18433  Marker_Tags_InletFile.clear();
18434 
18435  /*--- First, parse the marker tags to count how many total inlet markers
18436  we have now on the master. ---*/
18437 
18438  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
18439  for (iPoint = 0; iPoint < Buffer_Recv_nPoin[iProcessor]; iPoint++) {
18440  index = (iProcessor*MaxLocalPoint + iPoint)*MAX_STRING_SIZE;
18441  for (iChar = 0; iChar < MAX_STRING_SIZE; iChar++) {
18442  str_buf[iChar] = Buffer_Recv_Str[index + iChar];
18443  }
18444  Marker_Tags.push_back(str_buf);
18445  Marker_Tags_InletFile.push_back(str_buf);
18446  }
18447  }
18448 
18449  /*--- Sort and remove the duplicate inlet marker strings. ---*/
18450 
18451  sort(Marker_Tags_InletFile.begin(), Marker_Tags_InletFile.end());
18452  Marker_Tags_InletFile.erase(unique(Marker_Tags_InletFile.begin(),
18453  Marker_Tags_InletFile.end()),
18454  Marker_Tags_InletFile.end());
18455 
18456  /*--- Store the unique number of markers for writing later. ---*/
18457 
18458  nMarker_InletFile = Marker_Tags_InletFile.size();
18459 
18460  /*--- Count the number of rows (nodes) per marker. ---*/
18461 
18462  nRow_InletFile = new unsigned long[nMarker_InletFile];
18463  for (iMarker = 0; iMarker < nMarker_InletFile; iMarker++) {
18464  nRow_InletFile[iMarker] = 0;
18465  }
18466 
18467  /*--- Now count the number of points per marker. ---*/
18468 
18469  jPoint = 0;
18470  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
18471  for (iPoint = 0; iPoint < Buffer_Recv_nPoin[iProcessor]; iPoint++) {
18472  for (iMarker = 0; iMarker < nMarker_InletFile; iMarker++) {
18473  if (Marker_Tags_InletFile[iMarker] == Marker_Tags[jPoint]) {
18474  nRow_InletFile[iMarker]++;
18475  }
18476  }
18477  jPoint++;
18478  }
18479  }
18480 
18481  /*--- Now put the number of points per marker into cumulative storage.
18482  We will also create an extra counter to make sorting easier. ---*/
18483 
18484  nRowCum_InletFile = new unsigned long[nMarker_InletFile+1];
18485  nRowCum_Counter = new unsigned long[nMarker_InletFile+1];
18486 
18487  nRowCum_InletFile[0] = 0; nRowCum_Counter[0] = 0;
18488  for (iMarker = 0; iMarker < nMarker_InletFile; iMarker++) {
18489  nRowCum_InletFile[iMarker+1] = nRowCum_InletFile[iMarker] + nRow_InletFile[iMarker];
18490  nRowCum_Counter[iMarker+1] = nRowCum_Counter[iMarker] + nRow_InletFile[iMarker];
18491  }
18492 
18493  /*--- Load up the coordinates, sorted into chunks per marker. ---*/
18494 
18495  jPoint = 0; kPoint = 0;
18496  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
18497  for (iPoint = 0; iPoint < Buffer_Recv_nPoin[iProcessor]; iPoint++) {
18498  for (iMarker = 0; iMarker < nMarker_InletFile; iMarker++) {
18499  if (Marker_Tags_InletFile[iMarker] == Marker_Tags[kPoint]) {
18500 
18501  /*--- Find our current index for this marker and store coords. ---*/
18502 
18503  index = nRowCum_Counter[iMarker];
18504  InletCoords[0][index] = Buffer_Recv_X[jPoint];
18505  InletCoords[1][index] = Buffer_Recv_Y[jPoint];
18506  if (nDim == 3) InletCoords[2][index] = Buffer_Recv_Z[jPoint];
18507 
18508  /*--- Increment the counter for this marker. ---*/
18509 
18510  nRowCum_Counter[iMarker]++;
18511 
18512  }
18513  }
18514 
18515  /*--- Increment point counter for marker tags and data. ---*/
18516 
18517  kPoint++;
18518  jPoint++;
18519 
18520  }
18521 
18522  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
18523 
18524  jPoint = (iProcessor+1)*MaxLocalPoint;
18525 
18526  }
18527  }
18528 
18529  /*--- Immediately release the temporary data buffers. ---*/
18530 
18531  delete [] Buffer_Send_X;
18532  delete [] Buffer_Send_Y;
18533  if (Buffer_Send_Z != NULL) delete [] Buffer_Send_Z;
18534  delete [] Buffer_Send_Str;
18535  if (rank == MASTER_NODE) {
18536  delete [] Buffer_Recv_X;
18537  delete [] Buffer_Recv_Y;
18538  if (Buffer_Recv_Z != NULL) delete [] Buffer_Recv_Z;
18539  delete [] Buffer_Recv_nPoin;
18540  delete [] Buffer_Recv_Str;
18541  delete [] nRowCum_Counter;
18542  }
18543 
18544 }
18545 
18546 void COutput::Write_InletFile_Flow(CConfig *config, CGeometry *geometry, CSolver **solver) {
18547 
18548  unsigned short iMarker, iDim, iVar;
18549  unsigned long iPoint;
18550  su2double turb_val[2] = {0.0,0.0};
18551 
18552  const unsigned short nDim = geometry->GetnDim();
18553 
18554  bool turbulent = (config->GetKind_Solver() == RANS ||
18555  config->GetKind_Solver() == ADJ_RANS ||
18556  config->GetKind_Solver() == DISC_ADJ_RANS);
18557 
18558  unsigned short nVar_Turb = 0;
18559  if (turbulent)
18560  switch (config->GetKind_Turb_Model()) {
18561  case SA: case SA_NEG: case SA_E: case SA_COMP: case SA_E_COMP:
18562  nVar_Turb = 1;
18563  turb_val[0] = solver[TURB_SOL]->GetNuTilde_Inf();
18564  break;
18565  case SST:
18566  nVar_Turb = 2;
18567  turb_val[0] = solver[TURB_SOL]->GetTke_Inf();
18568  turb_val[1] = solver[TURB_SOL]->GetOmega_Inf();
18569  break;
18570  default:
18571  SU2_MPI::Error("Specified turbulence model unavailable or none selected", CURRENT_FUNCTION);
18572  break;
18573  }
18574 
18575  /*--- Count the number of columns that we have for this flow case.
18576  Here, we have nDim entries for node coordinates, 2 entries for the total
18577  conditions or mass flow, another nDim for the direction vector, and
18578  finally entries for the number of turbulence variables. ---*/
18579 
18580  unsigned short nCol_InletFile = nDim + 2 + nDim + nVar_Turb;
18581 
18582  /*--- Write the inlet profile file. Note that we have already merged
18583  all of the information for the markers and coordinates previously
18584  in the MergeInletCoordinates() routine. ---*/
18585 
18586  ofstream node_file("inlet_example.dat");
18587 
18588  node_file << "NMARK= " << nMarker_InletFile << endl;
18589 
18590  for (iMarker = 0; iMarker < nMarker_InletFile; iMarker++) {
18591 
18592  /*--- Access the default data for this marker. ---*/
18593 
18594  string Marker_Tag = Marker_Tags_InletFile[iMarker];
18595  su2double p_total = config->GetInlet_Ptotal(Marker_Tag);
18596  su2double t_total = config->GetInlet_Ttotal(Marker_Tag);
18597  su2double* flow_dir = config->GetInlet_FlowDir(Marker_Tag);
18598 
18599  /*--- Header information for this marker. ---*/
18600 
18601  node_file << "MARKER_TAG= " << Marker_Tag << endl;
18602  node_file << "NROW=" << nRow_InletFile[iMarker] << endl;
18603  node_file << "NCOL=" << nCol_InletFile << endl;
18604 
18605  node_file << setprecision(15);
18606  node_file << std::scientific;
18607 
18608  /*--- Loop over the data structure and write the coords and vars to file. ---*/
18609 
18610  for (iPoint = nRowCum_InletFile[iMarker]; iPoint < nRowCum_InletFile[iMarker+1]; iPoint++) {
18611 
18612  for (iDim = 0; iDim < nDim; iDim++) {
18613  node_file << InletCoords[iDim][iPoint] << "\t";
18614  }
18615  node_file << t_total << "\t" << p_total;
18616  for (iDim = 0; iDim < nDim; iDim++) {
18617  node_file << "\t" << flow_dir[iDim];
18618  }
18619  for (iVar = 0; iVar < nVar_Turb; iVar++) {
18620  node_file << "\t" << turb_val[iVar];
18621  }
18622  node_file << endl;
18623  }
18624 
18625  }
18626  node_file.close();
18627 
18628  /*--- Print a message to inform the user about the template file. ---*/
18629 
18630  stringstream err;
18631  err << endl;
18632  err << " Created a template inlet profile file with node coordinates" << endl;
18633  err << " and solver variables at `inlet_example.dat`." << endl;
18634  err << " You can use this file as a guide for making your own inlet" << endl;
18635  err << " specification." << endl << endl;
18636  SU2_MPI::Error(err.str(), CURRENT_FUNCTION);
18637 
18638 }
18639 
18641 
18642  unsigned short iDim, nDim = geometry->GetnDim();
18643 
18644  /*--- The master node alone owns all data found in this routine. ---*/
18645 
18646  if (rank == MASTER_NODE) {
18647 
18648  /*--- Deallocate memory for inlet coordinate data ---*/
18649 
18650  if (nRow_InletFile != NULL) delete [] nRow_InletFile;
18651  if (nRowCum_InletFile != NULL) delete [] nRowCum_InletFile;
18652 
18653  Marker_Tags_InletFile.clear();
18654 
18655  for (iDim = 0; iDim < nDim; iDim++) {
18656  if (InletCoords[iDim] != NULL) delete [] InletCoords[iDim];
18657  }
18658  if (InletCoords != NULL) delete [] InletCoords;
18659  }
18660 
18661 }
18662 
18663 void COutput::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geometry, CConfig *config, bool output) {
18664 
18665  unsigned short iDim, iMarker, iMarker_Analyze;
18666  unsigned long iVertex, iPoint;
18667  su2double Mach = 0.0, Pressure, Temperature = 0.0, TotalPressure = 0.0, TotalTemperature = 0.0,
18668  Enthalpy, Velocity[3], TangVel[3], Velocity2, MassFlow, Density, Area,
18669  AxiFactor = 1.0, SoundSpeed, Vn, Vn2, Vtang2, Weight = 1.0;
18670 
18671  su2double Gas_Constant = config->GetGas_ConstantND();
18672  su2double Gamma = config->GetGamma();
18673  unsigned short nMarker = config->GetnMarker_All();
18674  unsigned short nDim = geometry->GetnDim();
18675  unsigned short Kind_Average = config->GetKind_Average();
18676 
18677  bool compressible = config->GetKind_Regime() == COMPRESSIBLE;
18678  bool incompressible = config->GetKind_Regime() == INCOMPRESSIBLE;
18679  bool energy = config->GetEnergy_Equation();
18680 
18681 
18682  bool axisymmetric = config->GetAxisymmetric();
18683  unsigned short nMarker_Analyze = config->GetnMarker_Analyze();
18684 
18685  su2double *Vector = new su2double[nDim];
18686  su2double *Surface_MassFlow = new su2double[nMarker];
18687  su2double *Surface_Mach = new su2double[nMarker];
18688  su2double *Surface_Temperature = new su2double[nMarker];
18689  su2double *Surface_Density = new su2double[nMarker];
18690  su2double *Surface_Enthalpy = new su2double[nMarker];
18691  su2double *Surface_NormalVelocity = new su2double[nMarker];
18692  su2double *Surface_StreamVelocity2 = new su2double[nMarker];
18693  su2double *Surface_TransvVelocity2 = new su2double[nMarker];
18694  su2double *Surface_Pressure = new su2double[nMarker];
18695  su2double *Surface_TotalTemperature = new su2double[nMarker];
18696  su2double *Surface_TotalPressure = new su2double[nMarker];
18697  su2double *Surface_VelocityIdeal = new su2double[nMarker];
18698  su2double *Surface_Area = new su2double[nMarker];
18699  su2double *Surface_MassFlow_Abs = new su2double[nMarker];
18700 
18701  /*--- Compute the numerical fan face Mach number, and the total area of the inflow ---*/
18702 
18703  for (iMarker = 0; iMarker < nMarker; iMarker++) {
18704 
18705  Surface_MassFlow[iMarker] = 0.0;
18706  Surface_Mach[iMarker] = 0.0;
18707  Surface_Temperature[iMarker] = 0.0;
18708  Surface_Density[iMarker] = 0.0;
18709  Surface_Enthalpy[iMarker] = 0.0;
18710  Surface_NormalVelocity[iMarker] = 0.0;
18711  Surface_StreamVelocity2[iMarker] = 0.0;
18712  Surface_TransvVelocity2[iMarker] = 0.0;
18713  Surface_Pressure[iMarker] = 0.0;
18714  Surface_TotalTemperature[iMarker] = 0.0;
18715  Surface_TotalPressure[iMarker] = 0.0;
18716  Surface_VelocityIdeal[iMarker] = 0.0;
18717  Surface_Area[iMarker] = 0.0;
18718  Surface_MassFlow_Abs[iMarker] = 0.0;
18719 
18720  if (config->GetMarker_All_Analyze(iMarker) == YES) {
18721 
18722  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
18723  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
18724 
18725  if (geometry->node[iPoint]->GetDomain()) {
18726 
18727  geometry->vertex[iMarker][iVertex]->GetNormal(Vector);
18728 
18729  if (axisymmetric) {
18730  if (geometry->node[iPoint]->GetCoord(1) != 0.0)
18731  AxiFactor = 2.0*PI_NUMBER*geometry->node[iPoint]->GetCoord(1);
18732  else
18733  AxiFactor = 1.0;
18734  } else {
18735  AxiFactor = 1.0;
18736  }
18737 
18738  Density = solver->node[iPoint]->GetDensity();
18739  Velocity2 = 0.0; Area = 0.0; MassFlow = 0.0; Vn = 0.0; Vtang2 = 0.0;
18740 
18741  for (iDim = 0; iDim < nDim; iDim++) {
18742  Area += (Vector[iDim] * AxiFactor) * (Vector[iDim] * AxiFactor);
18743  Velocity[iDim] = solver->node[iPoint]->GetVelocity(iDim);
18744  Velocity2 += Velocity[iDim] * Velocity[iDim];
18745  Vn += Velocity[iDim] * Vector[iDim] * AxiFactor;
18746  MassFlow += Vector[iDim] * AxiFactor * Density * Velocity[iDim];
18747  }
18748 
18749  Area = sqrt (Area);
18750  if (AxiFactor == 0.0) Vn = 0.0; else Vn /= Area;
18751  Vn2 = Vn * Vn;
18752  Pressure = solver->node[iPoint]->GetPressure();
18753  SoundSpeed = solver->node[iPoint]->GetSoundSpeed();
18754 
18755  for (iDim = 0; iDim < nDim; iDim++) {
18756  TangVel[iDim] = Velocity[iDim] - Vn*Vector[iDim]*AxiFactor/Area;
18757  Vtang2 += TangVel[iDim]*TangVel[iDim];
18758  }
18759 
18760  if (incompressible){
18761  if (config->GetKind_DensityModel() == VARIABLE) {
18762  Mach = sqrt(solver->node[iPoint]->GetVelocity2())/
18763  sqrt(solver->node[iPoint]->GetSpecificHeatCp()*config->GetPressure_ThermodynamicND()/(solver->node[iPoint]->GetSpecificHeatCv()*solver->node[iPoint]->GetDensity()));
18764  } else {
18765  Mach = sqrt(solver->node[iPoint]->GetVelocity2())/
18766  sqrt(config->GetBulk_Modulus()/(solver->node[iPoint]->GetDensity()));
18767  }
18768  Temperature = solver->node[iPoint]->GetTemperature();
18769  Enthalpy = solver->node[iPoint]->GetSpecificHeatCp()*Temperature;
18770  TotalTemperature = Temperature + 0.5*Velocity2/solver->node[iPoint]->GetSpecificHeatCp();
18771  TotalPressure = Pressure + 0.5*Density*Velocity2;
18772  }
18773  else{
18774  Mach = sqrt(Velocity2)/SoundSpeed;
18775  Temperature = Pressure / (Gas_Constant * Density);
18776  Enthalpy = solver->node[iPoint]->GetEnthalpy();
18777  TotalTemperature = Temperature * (1.0 + Mach * Mach * 0.5 * (Gamma - 1.0));
18778  TotalPressure = Pressure * pow( 1.0 + Mach * Mach * 0.5 * (Gamma - 1.0), Gamma / (Gamma - 1.0));
18779  }
18780 
18781  /*--- Compute the mass Surface_MassFlow ---*/
18782 
18783  Surface_Area[iMarker] += Area;
18784  Surface_MassFlow[iMarker] += MassFlow;
18785  Surface_MassFlow_Abs[iMarker] += abs(MassFlow);
18786 
18787  if (Kind_Average == AVERAGE_MASSFLUX) Weight = abs(MassFlow);
18788  else if (Kind_Average == AVERAGE_AREA) Weight = abs(Area);
18789  else Weight = 1.0;
18790 
18791  Surface_Mach[iMarker] += Mach*Weight;
18792  Surface_Temperature[iMarker] += Temperature*Weight;
18793  Surface_Density[iMarker] += Density*Weight;
18794  Surface_Enthalpy[iMarker] += Enthalpy*Weight;
18795  Surface_NormalVelocity[iMarker] += Vn*Weight;
18796  Surface_Pressure[iMarker] += Pressure*Weight;
18797  Surface_TotalTemperature[iMarker] += TotalTemperature*Weight;
18798  Surface_TotalPressure[iMarker] += TotalPressure*Weight;
18799 
18800  /*--- For now, always used the area to weight the uniformities. ---*/
18801 
18802  Weight = abs(Area);
18803 
18804  Surface_StreamVelocity2[iMarker] += Vn2*Weight;
18805  Surface_TransvVelocity2[iMarker] += Vtang2*Weight;
18806 
18807  }
18808  }
18809 
18810  }
18811 
18812  }
18813 
18814  /*--- Copy to the appropriate structure ---*/
18815 
18816  su2double *Surface_MassFlow_Local = new su2double [nMarker_Analyze];
18817  su2double *Surface_Mach_Local = new su2double [nMarker_Analyze];
18818  su2double *Surface_Temperature_Local = new su2double [nMarker_Analyze];
18819  su2double *Surface_Density_Local = new su2double [nMarker_Analyze];
18820  su2double *Surface_Enthalpy_Local = new su2double [nMarker_Analyze];
18821  su2double *Surface_NormalVelocity_Local = new su2double [nMarker_Analyze];
18822  su2double *Surface_StreamVelocity2_Local = new su2double [nMarker_Analyze];
18823  su2double *Surface_TransvVelocity2_Local = new su2double [nMarker_Analyze];
18824  su2double *Surface_Pressure_Local = new su2double [nMarker_Analyze];
18825  su2double *Surface_TotalTemperature_Local = new su2double [nMarker_Analyze];
18826  su2double *Surface_TotalPressure_Local = new su2double [nMarker_Analyze];
18827  su2double *Surface_Area_Local = new su2double [nMarker_Analyze];
18828  su2double *Surface_MassFlow_Abs_Local = new su2double [nMarker_Analyze];
18829 
18830  su2double *Surface_MassFlow_Total = new su2double [nMarker_Analyze];
18831  su2double *Surface_Mach_Total = new su2double [nMarker_Analyze];
18832  su2double *Surface_Temperature_Total = new su2double [nMarker_Analyze];
18833  su2double *Surface_Density_Total = new su2double [nMarker_Analyze];
18834  su2double *Surface_Enthalpy_Total = new su2double [nMarker_Analyze];
18835  su2double *Surface_NormalVelocity_Total = new su2double [nMarker_Analyze];
18836  su2double *Surface_StreamVelocity2_Total = new su2double [nMarker_Analyze];
18837  su2double *Surface_TransvVelocity2_Total = new su2double [nMarker_Analyze];
18838  su2double *Surface_Pressure_Total = new su2double [nMarker_Analyze];
18839  su2double *Surface_TotalTemperature_Total = new su2double [nMarker_Analyze];
18840  su2double *Surface_TotalPressure_Total = new su2double [nMarker_Analyze];
18841  su2double *Surface_Area_Total = new su2double [nMarker_Analyze];
18842  su2double *Surface_MassFlow_Abs_Total = new su2double [nMarker_Analyze];
18843 
18844  su2double *Surface_MomentumDistortion_Total = new su2double [nMarker_Analyze];
18845 
18846  for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) {
18847  Surface_MassFlow_Local[iMarker_Analyze] = 0.0;
18848  Surface_Mach_Local[iMarker_Analyze] = 0.0;
18849  Surface_Temperature_Local[iMarker_Analyze] = 0.0;
18850  Surface_Density_Local[iMarker_Analyze] = 0.0;
18851  Surface_Enthalpy_Local[iMarker_Analyze] = 0.0;
18852  Surface_NormalVelocity_Local[iMarker_Analyze] = 0.0;
18853  Surface_StreamVelocity2_Local[iMarker_Analyze] = 0.0;
18854  Surface_TransvVelocity2_Local[iMarker_Analyze] = 0.0;
18855  Surface_Pressure_Local[iMarker_Analyze] = 0.0;
18856  Surface_TotalTemperature_Local[iMarker_Analyze] = 0.0;
18857  Surface_TotalPressure_Local[iMarker_Analyze] = 0.0;
18858  Surface_Area_Local[iMarker_Analyze] = 0.0;
18859  Surface_MassFlow_Abs_Local[iMarker_Analyze] = 0.0;
18860 
18861  Surface_MassFlow_Total[iMarker_Analyze] = 0.0;
18862  Surface_Mach_Total[iMarker_Analyze] = 0.0;
18863  Surface_Temperature_Total[iMarker_Analyze] = 0.0;
18864  Surface_Density_Total[iMarker_Analyze] = 0.0;
18865  Surface_Enthalpy_Total[iMarker_Analyze] = 0.0;
18866  Surface_NormalVelocity_Total[iMarker_Analyze] = 0.0;
18867  Surface_StreamVelocity2_Total[iMarker_Analyze] = 0.0;
18868  Surface_TransvVelocity2_Total[iMarker_Analyze] = 0.0;
18869  Surface_Pressure_Total[iMarker_Analyze] = 0.0;
18870  Surface_TotalTemperature_Total[iMarker_Analyze] = 0.0;
18871  Surface_TotalPressure_Total[iMarker_Analyze] = 0.0;
18872  Surface_Area_Total[iMarker_Analyze] = 0.0;
18873  Surface_MassFlow_Abs_Total[iMarker_Analyze] = 0.0;
18874 
18875  Surface_MomentumDistortion_Total[iMarker_Analyze] = 0.0;
18876 
18877  }
18878 
18879  /*--- Compute the numerical fan face Mach number, mach number, temperature and the total area ---*/
18880 
18881  for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
18882 
18883  if (config->GetMarker_All_Analyze(iMarker) == YES) {
18884 
18885  for (iMarker_Analyze= 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) {
18886 
18887  /*--- Add the Surface_MassFlow, and Surface_Area to the particular boundary ---*/
18888 
18889  if (config->GetMarker_All_TagBound(iMarker) == config->GetMarker_Analyze_TagBound(iMarker_Analyze)) {
18890  Surface_MassFlow_Local[iMarker_Analyze] += Surface_MassFlow[iMarker];
18891  Surface_Mach_Local[iMarker_Analyze] += Surface_Mach[iMarker];
18892  Surface_Temperature_Local[iMarker_Analyze] += Surface_Temperature[iMarker];
18893  Surface_Density_Local[iMarker_Analyze] += Surface_Density[iMarker];
18894  Surface_Enthalpy_Local[iMarker_Analyze] += Surface_Enthalpy[iMarker];
18895  Surface_NormalVelocity_Local[iMarker_Analyze] += Surface_NormalVelocity[iMarker];
18896  Surface_StreamVelocity2_Local[iMarker_Analyze] += Surface_StreamVelocity2[iMarker];
18897  Surface_TransvVelocity2_Local[iMarker_Analyze] += Surface_TransvVelocity2[iMarker];
18898  Surface_Pressure_Local[iMarker_Analyze] += Surface_Pressure[iMarker];
18899  Surface_TotalTemperature_Local[iMarker_Analyze] += Surface_TotalTemperature[iMarker];
18900  Surface_TotalPressure_Local[iMarker_Analyze] += Surface_TotalPressure[iMarker];
18901  Surface_Area_Local[iMarker_Analyze] += Surface_Area[iMarker];
18902  Surface_MassFlow_Abs_Local[iMarker_Analyze] += Surface_MassFlow_Abs[iMarker];
18903  }
18904 
18905  }
18906 
18907  }
18908 
18909  }
18910 
18911 #ifdef HAVE_MPI
18912 
18913  SU2_MPI::Allreduce(Surface_MassFlow_Local, Surface_MassFlow_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18914  SU2_MPI::Allreduce(Surface_Mach_Local, Surface_Mach_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18915  SU2_MPI::Allreduce(Surface_Temperature_Local, Surface_Temperature_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18916  SU2_MPI::Allreduce(Surface_Density_Local, Surface_Density_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18917  SU2_MPI::Allreduce(Surface_Enthalpy_Local, Surface_Enthalpy_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18918  SU2_MPI::Allreduce(Surface_NormalVelocity_Local, Surface_NormalVelocity_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18919  SU2_MPI::Allreduce(Surface_StreamVelocity2_Local, Surface_StreamVelocity2_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18920  SU2_MPI::Allreduce(Surface_TransvVelocity2_Local, Surface_TransvVelocity2_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18921  SU2_MPI::Allreduce(Surface_Pressure_Local, Surface_Pressure_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18922  SU2_MPI::Allreduce(Surface_TotalTemperature_Local, Surface_TotalTemperature_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18923  SU2_MPI::Allreduce(Surface_TotalPressure_Local, Surface_TotalPressure_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18924  SU2_MPI::Allreduce(Surface_Area_Local, Surface_Area_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18925  SU2_MPI::Allreduce(Surface_MassFlow_Abs_Local, Surface_MassFlow_Abs_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
18926 
18927 #else
18928 
18929  for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) {
18930  Surface_MassFlow_Total[iMarker_Analyze] = Surface_MassFlow_Local[iMarker_Analyze];
18931  Surface_Mach_Total[iMarker_Analyze] = Surface_Mach_Local[iMarker_Analyze];
18932  Surface_Temperature_Total[iMarker_Analyze] = Surface_Temperature_Local[iMarker_Analyze];
18933  Surface_Density_Total[iMarker_Analyze] = Surface_Density_Local[iMarker_Analyze];
18934  Surface_Enthalpy_Total[iMarker_Analyze] = Surface_Enthalpy_Local[iMarker_Analyze];
18935  Surface_NormalVelocity_Total[iMarker_Analyze] = Surface_NormalVelocity_Local[iMarker_Analyze];
18936  Surface_StreamVelocity2_Total[iMarker_Analyze] = Surface_StreamVelocity2_Local[iMarker_Analyze];
18937  Surface_TransvVelocity2_Total[iMarker_Analyze] = Surface_TransvVelocity2_Local[iMarker_Analyze];
18938  Surface_Pressure_Total[iMarker_Analyze] = Surface_Pressure_Local[iMarker_Analyze];
18939  Surface_TotalTemperature_Total[iMarker_Analyze] = Surface_TotalTemperature_Local[iMarker_Analyze];
18940  Surface_TotalPressure_Total[iMarker_Analyze] = Surface_TotalPressure_Local[iMarker_Analyze];
18941  Surface_Area_Total[iMarker_Analyze] = Surface_Area_Local[iMarker_Analyze];
18942  Surface_MassFlow_Abs_Total[iMarker_Analyze] = Surface_MassFlow_Abs_Local[iMarker_Analyze];
18943  }
18944 
18945 #endif
18946 
18947  /*--- Compute the value of Surface_Area_Total, and Surface_Pressure_Total, and
18948  set the value in the config structure for future use ---*/
18949 
18950  for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) {
18951 
18952  if (Kind_Average == AVERAGE_MASSFLUX) Weight = Surface_MassFlow_Abs_Total[iMarker_Analyze];
18953  else if (Kind_Average == AVERAGE_AREA) Weight = abs(Surface_Area_Total[iMarker_Analyze]);
18954  else Weight = 1.0;
18955 
18956  if (Weight != 0.0) {
18957  Surface_Mach_Total[iMarker_Analyze] /= Weight;
18958  Surface_Temperature_Total[iMarker_Analyze] /= Weight;
18959  Surface_Density_Total[iMarker_Analyze] /= Weight;
18960  Surface_Enthalpy_Total[iMarker_Analyze] /= Weight;
18961  Surface_NormalVelocity_Total[iMarker_Analyze] /= Weight;
18962  Surface_Pressure_Total[iMarker_Analyze] /= Weight;
18963  Surface_TotalTemperature_Total[iMarker_Analyze] /= Weight;
18964  Surface_TotalPressure_Total[iMarker_Analyze] /= Weight;
18965  }
18966  else {
18967  Surface_Mach_Total[iMarker_Analyze] = 0.0;
18968  Surface_Temperature_Total[iMarker_Analyze] = 0.0;
18969  Surface_Density_Total[iMarker_Analyze] = 0.0;
18970  Surface_Enthalpy_Total[iMarker_Analyze] = 0.0;
18971  Surface_NormalVelocity_Total[iMarker_Analyze] = 0.0;
18972  Surface_Pressure_Total[iMarker_Analyze] = 0.0;
18973  Surface_TotalTemperature_Total[iMarker_Analyze] = 0.0;
18974  Surface_TotalPressure_Total[iMarker_Analyze] = 0.0;
18975  }
18976 
18977  /*--- Compute flow uniformity parameters separately (always area for now). ---*/
18978 
18979  Area = fabs(Surface_Area_Total[iMarker_Analyze]);
18980 
18981  if (Area != 0.0) {
18982  Surface_MomentumDistortion_Total[iMarker_Analyze] = Surface_StreamVelocity2_Total[iMarker_Analyze]/(Surface_NormalVelocity_Total[iMarker_Analyze]*Surface_NormalVelocity_Total[iMarker_Analyze]*Area) - 1.0;
18983  Surface_StreamVelocity2_Total[iMarker_Analyze] /= Area;
18984  Surface_TransvVelocity2_Total[iMarker_Analyze] /= Area;
18985  }
18986  else {
18987  Surface_MomentumDistortion_Total[iMarker_Analyze] = 0.0;
18988  Surface_StreamVelocity2_Total[iMarker_Analyze] = 0.0;
18989  Surface_TransvVelocity2_Total[iMarker_Analyze] = 0.0;
18990  }
18991 
18992  }
18993 
18994  for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) {
18995 
18996  su2double MassFlow = Surface_MassFlow_Total[iMarker_Analyze] * config->GetDensity_Ref() * config->GetVelocity_Ref();
18997  if (config->GetSystemMeasurements() == US) MassFlow *= 32.174;
18998  config->SetSurface_MassFlow(iMarker_Analyze, MassFlow);
18999 
19000  su2double Mach = Surface_Mach_Total[iMarker_Analyze];
19001  config->SetSurface_Mach(iMarker_Analyze, Mach);
19002 
19003  su2double Temperature = Surface_Temperature_Total[iMarker_Analyze] * config->GetTemperature_Ref();
19004  config->SetSurface_Temperature(iMarker_Analyze, Temperature);
19005 
19006  su2double Pressure = Surface_Pressure_Total[iMarker_Analyze] * config->GetPressure_Ref();
19007  config->SetSurface_Pressure(iMarker_Analyze, Pressure);
19008 
19009  su2double Density = Surface_Density_Total[iMarker_Analyze] * config->GetDensity_Ref();
19010  config->SetSurface_Density(iMarker_Analyze, Density);
19011 
19012  su2double Enthalpy = Surface_Enthalpy_Total[iMarker_Analyze];
19013  config->SetSurface_Enthalpy(iMarker_Analyze, Enthalpy);
19014 
19015  su2double NormalVelocity = Surface_NormalVelocity_Total[iMarker_Analyze] * config->GetVelocity_Ref();
19016  config->SetSurface_NormalVelocity(iMarker_Analyze, NormalVelocity);
19017 
19018  su2double Uniformity = sqrt(Surface_StreamVelocity2_Total[iMarker_Analyze]) * config->GetVelocity_Ref();
19019  config->SetSurface_Uniformity(iMarker_Analyze, Uniformity);
19020 
19021  su2double SecondaryStrength = sqrt(Surface_TransvVelocity2_Total[iMarker_Analyze]) * config->GetVelocity_Ref();
19022  config->SetSurface_SecondaryStrength(iMarker_Analyze, SecondaryStrength);
19023 
19024  su2double MomentumDistortion = Surface_MomentumDistortion_Total[iMarker_Analyze];
19025  config->SetSurface_MomentumDistortion(iMarker_Analyze, MomentumDistortion);
19026 
19027  su2double SecondOverUniform = SecondaryStrength/Uniformity;
19028  config->SetSurface_SecondOverUniform(iMarker_Analyze, SecondOverUniform);
19029 
19030  su2double TotalTemperature = Surface_TotalTemperature_Total[iMarker_Analyze] * config->GetTemperature_Ref();
19031  config->SetSurface_TotalTemperature(iMarker_Analyze, TotalTemperature);
19032 
19033  su2double TotalPressure = Surface_TotalPressure_Total[iMarker_Analyze] * config->GetPressure_Ref();
19034  config->SetSurface_TotalPressure(iMarker_Analyze, TotalPressure);
19035 
19036  }
19037 
19038  /*--- Compute the average static pressure drop between two surfaces. Note
19039  that this assumes we have two surfaces being analyzed and that the outlet
19040  is first followed by the inlet. This is because we may also want to choose
19041  outlet values (temperature, uniformity, etc.) for our design problems,
19042  which require the outlet to be listed first. This is a simple first version
19043  that could be generalized to a different orders/lists/etc. ---*/
19044 
19045  for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) {
19046  if (nMarker_Analyze == 2) {
19047  su2double Pressure_Drop = (Surface_Pressure_Total[1]-Surface_Pressure_Total[0]) * config->GetPressure_Ref();
19048  config->SetSurface_PressureDrop(iMarker_Analyze, Pressure_Drop);
19049  } else {
19050  config->SetSurface_PressureDrop(iMarker_Analyze, 0.0);
19051  }
19052  }
19053 
19054  if ((rank == MASTER_NODE) && !config->GetDiscrete_Adjoint() && output) {
19055 
19056  cout.precision(6);
19057  cout.setf(ios::scientific, ios::floatfield);
19058  cout << endl << "Computing surface mean values." << endl << endl;
19059 
19060  for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) {
19061  cout << "Surface "<< config->GetMarker_Analyze_TagBound(iMarker_Analyze) << ":" << endl;
19062 
19063  if (nDim == 3) { if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Area (m^2): "; else cout << setw(20) << "Area (ft^2): "; }
19064  else { if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Area (m): "; else cout << setw(20) << "Area (ft): "; }
19065 
19066  if (config->GetSystemMeasurements() == SI) cout << setw(15) << fabs(Surface_Area_Total[iMarker_Analyze]);
19067  else if (config->GetSystemMeasurements() == US) cout << setw(15) << fabs(Surface_Area_Total[iMarker_Analyze])*12.0*12.0;
19068 
19069  cout << endl;
19070 
19071  su2double MassFlow = config->GetSurface_MassFlow(iMarker_Analyze);
19072  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Mf (kg/s): " << setw(15) << MassFlow;
19073  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "Mf (lbs/s): " << setw(15) << MassFlow;
19074 
19075  su2double NormalVelocity = config->GetSurface_NormalVelocity(iMarker_Analyze);
19076  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Vn (m/s): " << setw(15) << NormalVelocity;
19077  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "Vn (ft/s): " << setw(15) << NormalVelocity;
19078 
19079  cout << endl;
19080 
19081  su2double Uniformity = config->GetSurface_Uniformity(iMarker_Analyze);
19082  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Uniformity (m/s): " << setw(15) << Uniformity;
19083  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "Uniformity (ft/s): " << setw(15) << Uniformity;
19084 
19085  su2double SecondaryStrength = config->GetSurface_SecondaryStrength(iMarker_Analyze);
19086  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Secondary (m/s): " << setw(15) << SecondaryStrength;
19087  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "Secondary (ft/s): " << setw(15) << SecondaryStrength;
19088 
19089  cout << endl;
19090 
19091  su2double MomentumDistortion = config->GetSurface_MomentumDistortion(iMarker_Analyze);
19092  cout << setw(20) << "Mom. Distortion: " << setw(15) << MomentumDistortion;
19093 
19094  su2double SecondOverUniform = config->GetSurface_SecondOverUniform(iMarker_Analyze);
19095  cout << setw(20) << "Second/Uniform: " << setw(15) << SecondOverUniform;
19096 
19097  cout << endl;
19098 
19099  su2double Pressure = config->GetSurface_Pressure(iMarker_Analyze);
19100  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "P (Pa): " << setw(15) << Pressure;
19101  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "P (psf): " << setw(15) << Pressure;
19102 
19103  su2double TotalPressure = config->GetSurface_TotalPressure(iMarker_Analyze);
19104  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "PT (Pa): " << setw(15) <<TotalPressure;
19105  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "PT (psf): " << setw(15) <<TotalPressure;
19106 
19107  cout << endl;
19108 
19109  su2double Mach = config->GetSurface_Mach(iMarker_Analyze);
19110  cout << setw(20) << "Mach: " << setw(15) << Mach;
19111 
19112  su2double Density = config->GetSurface_Density(iMarker_Analyze);
19113  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Rho (kg/m^3): " << setw(15) << Density;
19114  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "Rho (lb/ft^3): " << setw(15) << Density*32.174;
19115 
19116  cout << endl;
19117 
19118  if (compressible || energy) {
19119  su2double Temperature = config->GetSurface_Temperature(iMarker_Analyze);
19120  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "T (K): " << setw(15) << Temperature;
19121  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "T (R): " << setw(15) << Temperature;
19122 
19123  su2double TotalTemperature = config->GetSurface_TotalTemperature(iMarker_Analyze);
19124  if (config->GetSystemMeasurements() == SI) cout << setw(20) << "TT (K): " << setw(15) << TotalTemperature;
19125  else if (config->GetSystemMeasurements() == US) cout << setw(20) << "TT (R): " << setw(15) << TotalTemperature;
19126 
19127  cout << endl;
19128  }
19129 
19130  }
19131  cout.unsetf(ios_base::floatfield);
19132 
19133  }
19134 
19135  delete [] Surface_MassFlow_Local;
19136  delete [] Surface_Mach_Local;
19137  delete [] Surface_Temperature_Local;
19138  delete [] Surface_Density_Local;
19139  delete [] Surface_Enthalpy_Local;
19140  delete [] Surface_NormalVelocity_Local;
19141  delete [] Surface_Pressure_Local;
19142  delete [] Surface_TotalTemperature_Local;
19143  delete [] Surface_TotalPressure_Local;
19144  delete [] Surface_Area_Local;
19145  delete [] Surface_MassFlow_Abs_Local;
19146 
19147  delete [] Surface_MassFlow_Total;
19148  delete [] Surface_Mach_Total;
19149  delete [] Surface_Temperature_Total;
19150  delete [] Surface_Density_Total;
19151  delete [] Surface_Enthalpy_Total;
19152  delete [] Surface_NormalVelocity_Total;
19153  delete [] Surface_Pressure_Total;
19154  delete [] Surface_TotalTemperature_Total;
19155  delete [] Surface_TotalPressure_Total;
19156  delete [] Surface_Area_Total;
19157  delete [] Surface_MassFlow_Abs_Total;
19158 
19159  delete [] Surface_MassFlow;
19160  delete [] Surface_Mach;
19161  delete [] Surface_Temperature;
19162  delete [] Surface_Density;
19163  delete [] Surface_Enthalpy;
19164  delete [] Surface_NormalVelocity;
19165  delete [] Surface_Pressure;
19166  delete [] Surface_TotalTemperature;
19167  delete [] Surface_TotalPressure;
19168  delete [] Surface_Area;
19169  delete [] Vector;
19170  delete [] Surface_VelocityIdeal;
19171  delete [] Surface_MassFlow_Abs;
19172 
19173 }
19174 
19175 void COutput::MergeConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short val_iZone) {
19176 
19177  /*--- Flags identifying the types of files to be written. ---*/
19178 
19179  bool Wrt_Vol = config->GetWrt_Vol_Sol();
19180  bool Wrt_Srf = config->GetWrt_Srf_Sol();
19181 
19182  /*--- Merge connectivity for each type of element (excluding halos). Note
19183  that we only need to merge the connectivity once, as it does not change
19184  during computation. Check whether the base file has been written. ---*/
19185 
19186  /*--- Merge volumetric grid. ---*/
19187 
19188  if (Wrt_Vol) {
19189 
19190  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Tria != 0))
19191  cout <<"Merging volumetric triangle grid connectivity." << endl;
19192  MergeVolumetricConnectivity_FEM(config, geometry, TRIANGLE );
19193 
19194  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Quad != 0))
19195  cout <<"Merging volumetric quadrilateral grid connectivity." << endl;
19196  MergeVolumetricConnectivity_FEM(config, geometry, QUADRILATERAL );
19197 
19198  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Tetr != 0))
19199  cout <<"Merging volumetric tetrahedron grid connectivity." << endl;
19200  MergeVolumetricConnectivity_FEM(config, geometry, TETRAHEDRON );
19201 
19202  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Hexa != 0))
19203  cout <<"Merging volumetric hexahedron grid connectivity." << endl;
19204  MergeVolumetricConnectivity_FEM(config, geometry, HEXAHEDRON );
19205 
19206  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Pris != 0))
19207  cout <<"Merging volumetric prism grid connectivity." << endl;
19208  MergeVolumetricConnectivity_FEM(config, geometry, PRISM );
19209 
19210  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Pyra != 0))
19211  cout <<"Merging volumetric pyramid grid connectivity." << endl;
19212  MergeVolumetricConnectivity_FEM(config, geometry, PYRAMID );
19213 
19214  }
19215 
19216  /*--- Merge surface grid. ---*/
19217 
19218  if (Wrt_Srf) {
19219 
19220  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Line != 0))
19221  cout <<"Merging surface line grid connectivity." << endl;
19222  MergeSurfaceConnectivity_FEM(config, geometry, LINE);
19223 
19224  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_BoundTria != 0))
19225  cout <<"Merging surface triangle grid connectivity." << endl;
19226  MergeSurfaceConnectivity_FEM(config, geometry, TRIANGLE);
19227 
19228  if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_BoundQuad != 0))
19229  cout <<"Merging surface quadrilateral grid connectivity." << endl;
19230  MergeSurfaceConnectivity_FEM(config, geometry, QUADRILATERAL);
19231 
19232  }
19233 
19234  /*--- Update total number of volume elements after merge. ---*/
19235 
19236  nGlobal_Elem = nGlobal_Tria + nGlobal_Quad + nGlobal_Tetr +
19237  nGlobal_Hexa + nGlobal_Pyra + nGlobal_Pris;
19238 
19239  /*--- Update total number of surface elements after merge. ---*/
19240 
19241  nSurf_Elem = nGlobal_Line + nGlobal_BoundTria + nGlobal_BoundQuad;
19242 
19243 }
19244 
19246 
19247  /*--- Local variables needed on all processors ---*/
19248 
19249  unsigned short iDim;
19250  unsigned long iPoint;
19251 
19252  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
19253  geometrical information for the FEM DG solver. ---*/
19254  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
19255 
19256  unsigned short nDim = DGGeometry->GetnDim();
19257 
19258  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
19259  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
19260 
19261  /*--- Create the map from the global DOF ID to the local index. ---*/
19262  vector<su2double> DOFsCoords;
19263  vector<unsigned long> globalID;
19264 
19265  /*--- Set the global ID and the coordinates of the local DOFs
19266  by looping over the owned volume elements. ---*/
19267  unsigned long nLocalPoint = 0;
19268  for(unsigned long l=0; l<nVolElemOwned; ++l) {
19269  for(unsigned short j=0; j<volElem[l].nDOFsSol; ++j) {
19270 
19271  const unsigned long globalIndex = volElem[l].offsetDOFsSolGlobal + j;
19272  globalID.push_back(globalIndex);
19273 
19274  const su2double *coor = volElem[l].coorSolDOFs.data() + j*nDim;
19275  for(unsigned short k=0; k<nDim; ++k) DOFsCoords.push_back(coor[k]);
19276 
19277  nLocalPoint++;
19278  }
19279  }
19280 
19281 #ifndef HAVE_MPI
19282 
19283  /*--- In serial, the single process has access to all geometry, so simply
19284  load the coordinates into the data structure. ---*/
19285 
19286  // need to double check for halos in parallel
19287 
19288  nGlobal_Poin = nLocalPoint;
19289  nGlobal_Doma = nLocalPoint;
19290 
19291  /*--- Allocate the coordinates data structure. ---*/
19292 
19293  Coords = new su2double*[nDim];
19294  for (iDim = 0; iDim < nDim; iDim++) {
19295  Coords[iDim] = new su2double[nGlobal_Poin];
19296  }
19297 
19298  /*--- Loop over the mesh to collect the coords of the local points ---*/
19299 
19300  for (iPoint = 0; iPoint < nLocalPoint; iPoint++) {
19301 
19302  /*--- Check if the node belongs to the domain (i.e, not a halo node).
19303  Sort by the global index, even in serial there is a renumbering (e.g. RCM). ---*/
19304 
19305  /*--- Retrieve the current coordinates at this node. ---*/
19306 
19307  unsigned long iGlobal_Index = globalID[iPoint];
19308 
19309  for (iDim = 0; iDim < nDim; iDim++) {
19310  Coords[iDim][iGlobal_Index] = DOFsCoords[iPoint*nDim+iDim];
19311 
19312  /*--- If US system, the output should be in inches ---*/
19313 
19314  if ((config->GetSystemMeasurements() == US) && (config->GetKind_SU2() != SU2_DEF)) {
19315  Coords[iDim][iGlobal_Index] *= 12.0;
19316  }
19317  }
19318  }
19319 
19320 #else
19321 
19322  /*--- MPI preprocessing ---*/
19323  int iProcessor, nProcessor = size;
19324  unsigned long jPoint;
19325 
19326  /*--- Local variables needed for merging the geometry with MPI. ---*/
19327 
19328  unsigned long Buffer_Send_nPoin[1], *Buffer_Recv_nPoin = NULL;
19329  unsigned long MaxLocalPoint = 0;
19330  unsigned long iGlobal_Index = 0, nBuffer_Scalar = 0;
19331 
19332  if (rank == MASTER_NODE) Buffer_Recv_nPoin = new unsigned long[nProcessor];
19333 
19334  /*--- Search all send/recv boundaries on this partition for any periodic
19335  nodes that were part of the original domain. We want to recover these
19336  for visualization purposes. ---*/
19337 
19338  // Need to double check halo layers
19339 
19340  Buffer_Send_nPoin[0] = nLocalPoint;
19341 
19342  /*--- Communicate the total number of nodes on this domain. ---*/
19343 
19344  SU2_MPI::Gather(&Buffer_Send_nPoin, 1, MPI_UNSIGNED_LONG,
19345  Buffer_Recv_nPoin, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
19346  SU2_MPI::Allreduce(&nLocalPoint, &MaxLocalPoint, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
19347 
19348  if (rank == MASTER_NODE) {
19349  nGlobal_Doma = 0;
19350  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
19351  nGlobal_Doma += Buffer_Recv_nPoin[iProcessor];
19352  }
19353  }
19354  nBuffer_Scalar = MaxLocalPoint;
19355 
19356  /*--- Send and Recv buffers. ---*/
19357 
19358  su2double *Buffer_Send_X = new su2double[MaxLocalPoint];
19359  su2double *Buffer_Recv_X = NULL;
19360 
19361  su2double *Buffer_Send_Y = new su2double[MaxLocalPoint];
19362  su2double *Buffer_Recv_Y = NULL;
19363 
19364  su2double *Buffer_Send_Z = NULL, *Buffer_Recv_Z = NULL;
19365  if (nDim == 3) Buffer_Send_Z = new su2double[MaxLocalPoint];
19366 
19367  unsigned long *Buffer_Send_GlobalIndex = new unsigned long[MaxLocalPoint];
19368  unsigned long *Buffer_Recv_GlobalIndex = NULL;
19369 
19370  /*--- Prepare the receive buffers in the master node only. ---*/
19371 
19372  if (rank == MASTER_NODE) {
19373 
19374  Buffer_Recv_X = new su2double[nProcessor*MaxLocalPoint];
19375  Buffer_Recv_Y = new su2double[nProcessor*MaxLocalPoint];
19376  if (nDim == 3) Buffer_Recv_Z = new su2double[nProcessor*MaxLocalPoint];
19377  Buffer_Recv_GlobalIndex = new unsigned long[nProcessor*MaxLocalPoint];
19378 
19379  /*--- Sum total number of nodes to be written and allocate arrays ---*/
19380  nGlobal_Poin = 0;
19381  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
19382  nGlobal_Poin += Buffer_Recv_nPoin[iProcessor];
19383  }
19384  Coords = new su2double*[nDim];
19385  for (iDim = 0; iDim < nDim; iDim++) {
19386  Coords[iDim] = new su2double[nGlobal_Poin];
19387  }
19388  }
19389 
19390  /*--- Main communication routine. Loop over each coordinate and perform
19391  the MPI comm. Temporary 1-D buffers are used to send the coordinates at
19392  all nodes on each partition to the master node. These are then unpacked
19393  by the master and sorted by global index in one large n-dim. array. ---*/
19394 
19395  /*--- Loop over this partition to collect the coords of the local points. ---*/
19396  jPoint = 0;
19397  for (iPoint = 0; iPoint < nLocalPoint; iPoint++) {
19398 
19399  /*--- Check for halos and write only if requested ---*/
19400  // if (!Local_Halo[iPoint] || Wrt_Halo) {
19401 
19402  /*--- Load local coords into the temporary send buffer. These were stored above ---*/
19403  Buffer_Send_X[jPoint] = DOFsCoords[iPoint*nDim+0];
19404  Buffer_Send_Y[jPoint] = DOFsCoords[iPoint*nDim+1];
19405  if (nDim == 3) Buffer_Send_Z[jPoint] = DOFsCoords[iPoint*nDim+2];
19406 
19407  /*--- If US system, the output should be in inches ---*/
19408 
19409  if ((config->GetSystemMeasurements() == US) && (config->GetKind_SU2() != SU2_DEF)) {
19410  Buffer_Send_X[jPoint] *= 12.0;
19411  Buffer_Send_Y[jPoint] *= 12.0;
19412  if (nDim == 3) Buffer_Send_Z[jPoint] *= 12.0;
19413  }
19414 
19415  /*--- Store the global index for this local node. ---*/
19416  Buffer_Send_GlobalIndex[jPoint] = globalID[iPoint];
19417 
19418  /*--- Increment jPoint as the counter. We need this because iPoint
19419  may include halo nodes that we skip over during this loop. ---*/
19420  jPoint++;
19421  // }
19422  }
19423 
19424  /*--- Gather the coordinate data on the master node using MPI. ---*/
19425 
19426  SU2_MPI::Gather(Buffer_Send_X, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_X, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
19427  SU2_MPI::Gather(Buffer_Send_Y, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Y, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
19428  if (nDim == 3) {
19429  SU2_MPI::Gather(Buffer_Send_Z, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Z, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
19430  }
19431  SU2_MPI::Gather(Buffer_Send_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
19432 
19433  /*--- The master node unpacks and sorts this variable by global index ---*/
19434 
19435  if (rank == MASTER_NODE) {
19436  jPoint = 0;
19437  for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) {
19438  for (iPoint = 0; iPoint < Buffer_Recv_nPoin[iProcessor]; iPoint++) {
19439  /*--- Get global index, then loop over each variable and store ---*/
19440  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
19441  if (iGlobal_Index >= nGlobal_Poin){
19442  cout << iGlobal_Index << " " << nGlobal_Poin << endl;
19443  }
19444  Coords[0][iGlobal_Index] = Buffer_Recv_X[jPoint];
19445  Coords[1][iGlobal_Index] = Buffer_Recv_Y[jPoint];
19446  if (nDim == 3) Coords[2][iGlobal_Index] = Buffer_Recv_Z[jPoint];
19447  jPoint++;
19448  }
19449  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
19450  jPoint = (iProcessor+1)*nBuffer_Scalar;
19451  }
19452  }
19453 
19454  /*--- Immediately release the temporary data buffers. ---*/
19455 
19456  // delete [] Local_Halo;
19457  delete [] Buffer_Send_X;
19458  delete [] Buffer_Send_Y;
19459  if (Buffer_Send_Z != NULL) delete [] Buffer_Send_Z;
19460  delete [] Buffer_Send_GlobalIndex;
19461  if (rank == MASTER_NODE) {
19462  delete [] Buffer_Recv_X;
19463  delete [] Buffer_Recv_Y;
19464  if (Buffer_Recv_Z != NULL) delete [] Buffer_Recv_Z;
19465  delete [] Buffer_Recv_GlobalIndex;
19466  delete [] Buffer_Recv_nPoin;
19467  }
19468 
19469 #endif
19470 
19471 }
19472 
19473 void COutput::MergeVolumetricConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) {
19474 
19475  int iProcessor;
19476  unsigned short NODES_PER_ELEMENT = 0;
19477  unsigned long iNode, jNode;
19478  unsigned long iElem = 0;
19479  unsigned long nLocalElem = 0, nElem_Total = 0;
19480 
19481  unsigned long jElem;
19482 
19483  unsigned long Buffer_Send_nElem[1], *Buffer_Recv_nElem = NULL;
19484  unsigned long nBuffer_Scalar = 0;
19485  unsigned long kNode = 0, kElem = 0;
19486  unsigned long MaxLocalElem = 0;
19487 
19488  bool Wrt_Halo = config->GetWrt_Halo();
19489  bool *Write_Elem = NULL;
19490 
19491  int *Conn_Elem = NULL;
19492 
19493  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
19494  geometrical information for the FEM DG solver. ---*/
19495  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
19496 
19497  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
19498 
19499  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
19500 
19501  const CFEMStandardElement *standardElementsSol = DGGeometry->GetStandardElementsSol();
19502 
19503  /* Define the vectors for the connectivity of the local linear subelements. */
19504  vector<unsigned long> volumeConn;
19505 
19506  /*--- Create the map from the global DOF ID to the local index. ---*/
19507  map<unsigned long, unsigned long> mapLocal2Global;
19508  unsigned long ii = 0;
19509  for(unsigned long i=0; i<nVolElemOwned; ++i) {
19510  for(unsigned short j=0; j<volElem[i].nDOFsSol; ++j, ++ii) {
19511  mapLocal2Global[ii] = volElem[i].offsetDOFsSolGlobal+j;
19512  }
19513  }
19514 
19515  /*--- Counter for keeping track of the number of this element locally. ---*/
19516  nLocalElem = 0;
19517  for(unsigned long i=0; i<nVolElemOwned; ++i) {
19518 
19519  /* Determine the necessary data from the corresponding standard elem,
19520  such as the number of linear sub elements, the number of DOFs per
19521  linear sub element and the corresponding local connectivity. */
19522  const unsigned short ind = volElem[i].indStandardElement;
19523  const unsigned short VTK_Type1 = standardElementsSol[ind].GetVTK_Type1();
19524  const unsigned short VTK_Type2 = standardElementsSol[ind].GetVTK_Type2();
19525 
19526  /*--- Only store the linear sub elements if they are of
19527  the current type that we are merging. ---*/
19528  if (Elem_Type == VTK_Type1) {
19529 
19530  const unsigned short nSubElems = standardElementsSol[ind].GetNSubElemsType1();
19531  const unsigned short nDOFsPerSubElem = standardElementsSol[ind].GetNDOFsPerSubElem(VTK_Type1);
19532  const unsigned short *connSubElems = standardElementsSol[ind].GetSubConnType1();
19533 
19534  /* Loop over the number of subfaces and store the required data. */
19535  unsigned short kk = 0;
19536  for(unsigned short j=0; j<nSubElems; ++j) {
19537 
19538  /*--- Store the global index for the surface conn ---*/
19539  for(unsigned short k=0; k<nDOFsPerSubElem; ++k, ++kk)
19540  volumeConn.push_back(mapLocal2Global[volElem[i].offsetDOFsSolLocal+connSubElems[kk]]);
19541 
19542  nLocalElem++;
19543  }
19544 
19545  } else if (Elem_Type == VTK_Type2) {
19546 
19547  const unsigned short nSubElems = standardElementsSol[ind].GetNSubElemsType2();
19548  const unsigned short nDOFsPerSubElem = standardElementsSol[ind].GetNDOFsPerSubElem(VTK_Type2);
19549  const unsigned short *connSubElems = standardElementsSol[ind].GetSubConnType2();
19550 
19551  /* Loop over the number of subfaces and store the required data. */
19552  unsigned short kk = 0;
19553  for(unsigned short j=0; j<nSubElems; ++j) {
19554 
19555  /*--- Store the global index for the surface conn ---*/
19556  for(unsigned short k=0; k<nDOFsPerSubElem; ++k, ++kk)
19557  volumeConn.push_back(mapLocal2Global[volElem[i].offsetDOFsSolLocal+connSubElems[kk]]);
19558 
19559  nLocalElem++;
19560  }
19561  }
19562  }
19563 
19564  /*--- Store the local number of this element type and the number of nodes
19565  per this element type. In serial, this will be the total number of this
19566  element type in the entire mesh. In parallel, it is the number on only
19567  the current partition. ---*/
19568 
19569  switch (Elem_Type) {
19570  case TRIANGLE:
19571  NODES_PER_ELEMENT = N_POINTS_TRIANGLE;
19572  break;
19573  case QUADRILATERAL:
19574  NODES_PER_ELEMENT = N_POINTS_QUADRILATERAL;
19575  break;
19576  case TETRAHEDRON:
19577  NODES_PER_ELEMENT = N_POINTS_TETRAHEDRON;
19578  break;
19579  case HEXAHEDRON:
19580  NODES_PER_ELEMENT = N_POINTS_HEXAHEDRON;
19581  break;
19582  case PRISM:
19583  NODES_PER_ELEMENT = N_POINTS_PRISM;
19584  break;
19585  case PYRAMID:
19586  NODES_PER_ELEMENT = N_POINTS_PYRAMID;
19587  break;
19588  default:
19589  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
19590  }
19591 
19592  /*--- Find the max number of this element type among all
19593  partitions and set up buffers. ---*/
19594 
19595  Buffer_Send_nElem[0] = nLocalElem;
19596  if (rank == MASTER_NODE) Buffer_Recv_nElem = new unsigned long[size];
19597 
19598 #ifdef HAVE_MPI
19599  SU2_MPI::Allreduce(&nLocalElem, &MaxLocalElem, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
19600  SU2_MPI::Gather(&Buffer_Send_nElem, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nElem, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
19601 #else
19602  MaxLocalElem = nLocalElem;
19603  Buffer_Recv_nElem[0] = Buffer_Send_nElem[0];
19604 #endif
19605 
19606  nBuffer_Scalar = MaxLocalElem*NODES_PER_ELEMENT;
19607 
19608  /*--- Send and Recv buffers ---*/
19609 
19610  unsigned long *Buffer_Send_Elem = new unsigned long[nBuffer_Scalar];
19611  unsigned long *Buffer_Recv_Elem = NULL;
19612 
19613  unsigned short *Buffer_Send_Halo = new unsigned short[MaxLocalElem];
19614  unsigned short *Buffer_Recv_Halo = NULL;
19615 
19616  /*--- Prepare the receive buffers on the master node only. ---*/
19617 
19618  if (rank == MASTER_NODE) {
19619  Buffer_Recv_Elem = new unsigned long[size*nBuffer_Scalar];
19620  Buffer_Recv_Halo = new unsigned short[size*MaxLocalElem];
19621  if (MaxLocalElem > 0) Conn_Elem = new int[size*MaxLocalElem*NODES_PER_ELEMENT];
19622  }
19623 
19624  /*--- Loop over all elements in this partition and load the
19625  elements of the current type into the buffer to be sent to
19626  the master node. ---*/
19627 
19628  jNode = 0;
19629  for (iElem = 0; iElem < nLocalElem; iElem++) {
19630 
19631  /*--- Loop over all nodes in this element and load the
19632  connectivity into the send buffer. ---*/
19633  Buffer_Send_Halo[iElem] = false;
19634  for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) {
19635 
19636  /*--- Store the global index values directly. ---*/
19637 
19638  Buffer_Send_Elem[jNode] = volumeConn[iElem*NODES_PER_ELEMENT+iNode];
19639 
19640  /*--- Increment jNode as the counter. We need this because iElem
19641  may include other elements that we skip over during this loop. ---*/
19642 
19643  jNode++;
19644  }
19645  }
19646 
19647  /*--- Gather the element connectivity information. ---*/
19648 
19649 #ifdef HAVE_MPI
19650  SU2_MPI::Gather(Buffer_Send_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
19651  SU2_MPI::Gather(Buffer_Send_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, Buffer_Recv_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, MASTER_NODE, MPI_COMM_WORLD);
19652 #else
19653  for (unsigned long iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Elem[iPoint] = Buffer_Send_Elem[iPoint];
19654  for (unsigned long iPoint = 0; iPoint < MaxLocalElem; iPoint++) Buffer_Recv_Halo[iPoint] = Buffer_Send_Halo[iPoint];
19655 #endif
19656 
19657  /*--- The master node unpacks and sorts the connectivity. ---*/
19658 
19659  if (rank == MASTER_NODE) {
19660 
19661  /*--- We need to remove any duplicate elements (halo cells) that
19662  exist on multiple partitions. Start by initializing all elements
19663  to the "write" state by using a boolean array. ---*/
19664 
19665  Write_Elem = new bool[size*MaxLocalElem];
19666  for (iElem = 0; iElem < size*MaxLocalElem; iElem++) {
19667  Write_Elem[iElem] = true;
19668  }
19669 
19670  /*--- Remove the rind layer from the solution only if requested ---*/
19671 
19672  if (!Wrt_Halo) {
19673 
19674  /*--- Loop for flagging duplicate elements so that they are not
19675  included in the final connectivity list. ---*/
19676 
19677  kElem = 0;
19678  for (iProcessor = 0; iProcessor < size; iProcessor++) {
19679  for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) {
19680 
19681  /*--- Check if this element was marked as a halo. ---*/
19682  if (Buffer_Recv_Halo[kElem+iElem])
19683  Write_Elem[kElem+iElem] = false;
19684 
19685  }
19686  kElem = (iProcessor+1)*MaxLocalElem;
19687  }
19688  }
19689 
19690  /*--- Store the unique connectivity list for this element type. ---*/
19691 
19692  jNode = 0; kNode = 0; jElem = 0; nElem_Total = 0;
19693  for (iProcessor = 0; iProcessor < size; iProcessor++) {
19694  for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) {
19695 
19696  /*--- Only write the elements that were flagged for it. ---*/
19697  if (Write_Elem[jElem+iElem]) {
19698 
19699  /*--- Increment total count for this element type ---*/
19700  nElem_Total++;
19701 
19702  /*--- Get global index, then loop over each variable and store.
19703  Note that we are adding one to the index value because CGNS/Tecplot
19704  use 1-based indexing.---*/
19705 
19706  for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) {
19707  Conn_Elem[kNode] = (int)Buffer_Recv_Elem[jNode+iElem*NODES_PER_ELEMENT+iNode] + 1;
19708  kNode++;
19709  }
19710  }
19711  }
19712  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
19713  jElem = (iProcessor+1)*MaxLocalElem;
19714  jNode = (iProcessor+1)*nBuffer_Scalar;
19715  }
19716  }
19717 
19718  /*--- Immediately release the temporary buffers. ---*/
19719  delete [] Buffer_Send_Elem;
19720  delete [] Buffer_Send_Halo;
19721  if (rank == MASTER_NODE) {
19722  delete [] Buffer_Recv_nElem;
19723  delete [] Buffer_Recv_Elem;
19724  delete [] Buffer_Recv_Halo;
19725  delete [] Write_Elem;
19726  }
19727 
19728  /*--- Store the particular global element count in the class data,
19729  and set the class data pointer to the connectivity array. ---*/
19730 
19731  if (rank == MASTER_NODE) {
19732  switch (Elem_Type) {
19733  case TRIANGLE:
19734  nGlobal_Tria = nElem_Total;
19735  if (nGlobal_Tria > 0) Conn_Tria = Conn_Elem;
19736  break;
19737  case QUADRILATERAL:
19738  nGlobal_Quad = nElem_Total;
19739  if (nGlobal_Quad > 0) Conn_Quad = Conn_Elem;
19740  break;
19741  case TETRAHEDRON:
19742  nGlobal_Tetr = nElem_Total;
19743  if (nGlobal_Tetr > 0) Conn_Tetr = Conn_Elem;
19744  break;
19745  case HEXAHEDRON:
19746  nGlobal_Hexa = nElem_Total;
19747  if (nGlobal_Hexa > 0) Conn_Hexa = Conn_Elem;
19748  break;
19749  case PRISM:
19750  nGlobal_Pris = nElem_Total;
19751  if (nGlobal_Pris > 0) Conn_Pris = Conn_Elem;
19752  break;
19753  case PYRAMID:
19754  nGlobal_Pyra = nElem_Total;
19755  if (nGlobal_Pyra > 0) Conn_Pyra = Conn_Elem;
19756  break;
19757  default:
19758  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
19759  }
19760  }
19761 
19762 }
19763 
19764 void COutput::MergeSurfaceConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) {
19765 
19766  unsigned short NODES_PER_ELEMENT = 0;
19767 
19768  unsigned long iNode, jNode;
19769  unsigned long iElem = 0;
19770  unsigned long nLocalElem = 0, nElem_Total = 0;
19771 
19772  int iProcessor;
19773  unsigned long jElem;
19774 
19775  unsigned long Buffer_Send_nElem[1], *Buffer_Recv_nElem = NULL;
19776  unsigned long nBuffer_Scalar = 0;
19777  unsigned long kNode = 0, kElem = 0;
19778  unsigned long MaxLocalElem = 0;
19779 
19780  bool Wrt_Halo = config->GetWrt_Halo();
19781  bool *Write_Elem = NULL;
19782 
19783  int *Conn_Elem = NULL;
19784 
19785  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
19786  geometrical information for the FEM DG solver. ---*/
19787  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
19788 
19789  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
19790 
19791  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
19792 
19793  const CBoundaryFEM *boundaries = DGGeometry->GetBoundaries();
19794 
19795  const CFEMStandardBoundaryFace *standardBoundaryFacesSol = DGGeometry->GetStandardBoundaryFacesSol();
19796 
19797  /*--- Create the map from the global DOF ID to the local index. ---*/
19798  map<unsigned long, unsigned long> mapLocal2Global;
19799  unsigned long ii = 0;
19800  for(unsigned long i=0; i<nVolElemOwned; ++i) {
19801  for(unsigned short j=0; j<volElem[i].nDOFsSol; ++j, ++ii) {
19802  mapLocal2Global[ii] = volElem[i].offsetDOFsSolGlobal+j;
19803  }
19804  }
19805 
19806  /* Define the vectors for the connectivity of the local linear subelements. */
19807  vector<unsigned long> surfaceConn;
19808 
19809  /*--- Counter for keeping track of the number of this element locally. ---*/
19810  nLocalElem = 0;
19811 
19812  /* Loop over the boundary markers. */
19813  for(unsigned short iMarker=0; iMarker < config->GetnMarker_All(); ++iMarker) {
19814  if( !boundaries[iMarker].periodicBoundary ) {
19815 
19816  /* Check for markers to be plotted. */
19817  if (config->GetMarker_All_Plotting(iMarker) == YES) {
19818 
19819  /* Loop over the surface elements of this marker. */
19820  const vector<CSurfaceElementFEM> &surfElem = boundaries[iMarker].surfElem;
19821  for(unsigned long i=0; i<surfElem.size(); ++i) {
19822 
19823  /* Determine the necessary data from the corresponding standard face,
19824  such as the number of linear subfaces, the number of DOFs per
19825  linear subface and the corresponding local connectivity. */
19826  const unsigned short ind = surfElem[i].indStandardElement;
19827  const unsigned short VTK_Type = standardBoundaryFacesSol[ind].GetVTK_Type();
19828 
19829  /*--- Only store the linear sub-elements if they are of
19830  the current type that we are merging. ---*/
19831  if (VTK_Type == Elem_Type) {
19832 
19833  const unsigned short nSubFaces = standardBoundaryFacesSol[ind].GetNSubFaces();
19834  const unsigned short nDOFsPerFace = standardBoundaryFacesSol[ind].GetNDOFsPerSubFace();
19835  const unsigned short *connSubFaces = standardBoundaryFacesSol[ind].GetSubFaceConn();
19836 
19837  /* Loop over the number of subfaces and store the required data. */
19838  unsigned short ii = 0;
19839  for(unsigned short j=0; j<nSubFaces; ++j) {
19840 
19841  /*--- Store the global index for the surface conn ---*/
19842  for(unsigned short k=0; k<nDOFsPerFace; ++k, ++ii)
19843  surfaceConn.push_back(mapLocal2Global[surfElem[i].DOFsSolFace[connSubFaces[ii]]]);
19844 
19845  nLocalElem++;
19846  }
19847  }
19848  }
19849  }
19850  }
19851  }
19852 
19853  switch (Elem_Type) {
19854  case LINE:
19855  NODES_PER_ELEMENT = N_POINTS_LINE;
19856  break;
19857  case TRIANGLE:
19858  NODES_PER_ELEMENT = N_POINTS_TRIANGLE;
19859  break;
19860  case QUADRILATERAL:
19861  NODES_PER_ELEMENT = N_POINTS_QUADRILATERAL;
19862  break;
19863  default:
19864  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
19865  }
19866 
19867  /*--- Find the max number of this element type among all
19868  partitions and set up buffers. ---*/
19869 
19870  Buffer_Send_nElem[0] = nLocalElem;
19871  if (rank == MASTER_NODE) Buffer_Recv_nElem = new unsigned long[size];
19872 
19873 #ifdef HAVE_MPI
19874  SU2_MPI::Allreduce(&nLocalElem, &MaxLocalElem, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
19875  SU2_MPI::Gather(&Buffer_Send_nElem, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nElem, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
19876 #else
19877  MaxLocalElem = nLocalElem;
19878  Buffer_Recv_nElem[0] = Buffer_Send_nElem[0];
19879 #endif
19880 
19881  nBuffer_Scalar = MaxLocalElem*NODES_PER_ELEMENT;
19882 
19883  /*--- Send and Recv buffers ---*/
19884 
19885  unsigned long *Buffer_Send_Elem = new unsigned long[nBuffer_Scalar];
19886  unsigned long *Buffer_Recv_Elem = NULL;
19887 
19888  unsigned short *Buffer_Send_Halo = new unsigned short[MaxLocalElem];
19889  unsigned short *Buffer_Recv_Halo = NULL;
19890 
19891  /*--- Prepare the receive buffers on the master node only. ---*/
19892 
19893  if (rank == MASTER_NODE) {
19894  Buffer_Recv_Elem = new unsigned long[size*nBuffer_Scalar];
19895  Buffer_Recv_Halo = new unsigned short[size*MaxLocalElem];
19896  if (MaxLocalElem > 0) Conn_Elem = new int[size*MaxLocalElem*NODES_PER_ELEMENT];
19897  }
19898 
19899  /*--- Loop over all elements in this partition and load the
19900  elements of the current type into the buffer to be sent to
19901  the master node. ---*/
19902  jNode = 0;
19903  for (iElem = 0; iElem < nLocalElem; iElem++) {
19904 
19905  /*--- Loop over all nodes in this element and load the
19906  connectivity into the send buffer. ---*/
19907  Buffer_Send_Halo[iElem] = false;
19908  for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) {
19909 
19910  /*--- Store the global index values directly. ---*/
19911  Buffer_Send_Elem[jNode] = surfaceConn[iElem*NODES_PER_ELEMENT+iNode];
19912 
19913  /*--- Increment jNode as the counter for the buffer array. ---*/
19914  jNode++;
19915  }
19916  }
19917 
19918  /*--- Gather the element connectivity information. ---*/
19919 
19920 #ifdef HAVE_MPI
19921  SU2_MPI::Gather(Buffer_Send_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
19922  SU2_MPI::Gather(Buffer_Send_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, Buffer_Recv_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, MASTER_NODE, MPI_COMM_WORLD);
19923 #else
19924  for (unsigned long iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Elem[iPoint] = Buffer_Send_Elem[iPoint];
19925  for (unsigned long iPoint = 0; iPoint < MaxLocalElem; iPoint++) Buffer_Recv_Halo[iPoint] = Buffer_Send_Halo[iPoint];
19926 #endif
19927 
19928  /*--- The master node unpacks and sorts the connectivity. ---*/
19929 
19930  if (rank == MASTER_NODE) {
19931 
19932  /*--- We need to remove any duplicate elements (halo cells) that
19933  exist on multiple partitions. Start by initializing all elements
19934  to the "write" state by using a boolean array. ---*/
19935 
19936  Write_Elem = new bool[size*MaxLocalElem];
19937  for (iElem = 0; iElem < size*MaxLocalElem; iElem++) {
19938  Write_Elem[iElem] = true;
19939  }
19940 
19941  /*--- Remove the rind layer from the solution only if requested ---*/
19942 
19943  if (!Wrt_Halo) {
19944 
19945  /*--- Loop for flagging duplicate elements so that they are not
19946  included in the final connectivity list. ---*/
19947 
19948  kElem = 0;
19949  for (iProcessor = 0; iProcessor < size; iProcessor++) {
19950  for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) {
19951 
19952  /*--- Check if this element was marked as a halo. ---*/
19953  if (Buffer_Recv_Halo[kElem+iElem])
19954  Write_Elem[kElem+iElem] = false;
19955 
19956  }
19957  kElem = (iProcessor+1)*MaxLocalElem;
19958  }
19959  }
19960 
19961  /*--- Store the unique connectivity list for this element type. ---*/
19962 
19963  jNode = 0; kNode = 0; jElem = 0; nElem_Total = 0;
19964  for (iProcessor = 0; iProcessor < size; iProcessor++) {
19965  for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) {
19966 
19967  /*--- Only write the elements that were flagged for it. ---*/
19968  if (Write_Elem[jElem+iElem]) {
19969 
19970  /*--- Increment total count for this element type ---*/
19971  nElem_Total++;
19972 
19973  /*--- Get global index, then loop over each variable and store.
19974  Note that we are adding one to the index value because CGNS/Tecplot
19975  use 1-based indexing.---*/
19976 
19977  for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) {
19978  Conn_Elem[kNode] = (int)Buffer_Recv_Elem[jNode+iElem*NODES_PER_ELEMENT+iNode] + 1;
19979  kNode++;
19980  }
19981  }
19982  }
19983  /*--- Adjust jNode to index of next proc's data in the buffers. ---*/
19984  jElem = (iProcessor+1)*MaxLocalElem;
19985  jNode = (iProcessor+1)*nBuffer_Scalar;
19986  }
19987  }
19988 
19989  /*--- Immediately release the temporary buffers. ---*/
19990  delete [] Buffer_Send_Elem;
19991  delete [] Buffer_Send_Halo;
19992  if (rank == MASTER_NODE) {
19993  delete [] Buffer_Recv_nElem;
19994  delete [] Buffer_Recv_Elem;
19995  delete [] Buffer_Recv_Halo;
19996  delete [] Write_Elem;
19997  }
19998 
19999  /*--- Store the particular global element count in the class data,
20000  and set the class data pointer to the connectivity array. ---*/
20001 
20002  if (rank == MASTER_NODE) {
20003  switch (Elem_Type) {
20004  case LINE:
20005  nGlobal_Line = nElem_Total;
20006  if (nGlobal_Line > 0) Conn_Line = Conn_Elem;
20007  break;
20008  case TRIANGLE:
20009  nGlobal_BoundTria = nElem_Total;
20010  if (nGlobal_BoundTria > 0) Conn_BoundTria = Conn_Elem;
20011  break;
20012  case QUADRILATERAL:
20013  nGlobal_BoundQuad = nElem_Total;
20014  if (nGlobal_BoundQuad > 0) Conn_BoundQuad = Conn_Elem;
20015  break;
20016  default:
20017  SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION);
20018  }
20019  }
20020 }
20021 
20022 void COutput::MergeSolution_FEM(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
20023 
20024  unsigned short Kind_Solver = config->GetKind_Solver();
20025  unsigned short iVar = 0, FirstIndex = NONE, SecondIndex = NONE, ThirdIndex = NONE;
20026  unsigned short nVar_First = 0, nVar_Second = 0, nVar_Third = 0;
20027 
20028  unsigned long iPoint = 0, jPoint = 0;
20029 
20030  unsigned long Buffer_Send_nPoint[1], *Buffer_Recv_nPoint = NULL;
20031  unsigned long nLocalPoint = 0, MaxLocalPoint = 0;
20032  unsigned long iGlobal_Index = 0, nBuffer_Scalar = 0;
20033 
20034  int iProcessor;
20035 
20036  /*--- Prepare send buffers for the conservative variables. Need to
20037  find the total number of conservative variables and also the
20038  index for their particular solution container. ---*/
20039 
20040  switch (Kind_Solver) {
20041  case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_LES: FirstIndex = FLOW_SOL; SecondIndex = NONE; ThirdIndex = NONE; break;
20042  default: SecondIndex = NONE; ThirdIndex = NONE; break;
20043  }
20044 
20045  nVar_First = solver[FirstIndex]->GetnVar();
20046  if (SecondIndex != NONE) nVar_Second = solver[SecondIndex]->GetnVar();
20047  if (ThirdIndex != NONE) nVar_Third = solver[ThirdIndex]->GetnVar();
20048  nVar_Consv = nVar_First + nVar_Second + nVar_Third;
20049  nVar_Total = nVar_Consv;
20050 
20051  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
20052  geometrical information for the FEM DG solver. ---*/
20053  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
20054 
20055  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
20056  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
20057 
20058  /*--- Create the map from the global DOF ID to the local index. ---*/
20059  map<unsigned long, unsigned long> mapLocal2Global;
20060  vector<su2double> DOFsSol;
20061  vector<unsigned long> globalID;
20062 
20063  /*--- Update the solution by looping over the owned volume elements. ---*/
20064  for(unsigned long l=0; l<nVolElemOwned; ++l) {
20065 
20066  /* Set the pointers for the residual and solution for this element. */
20067  const unsigned long offset = nVar_Consv*volElem[l].offsetDOFsSolLocal;
20068  su2double *solDOFs = solver[FirstIndex]->GetVecSolDOFs() + offset;
20069 
20070  /* Loop over the DOFs for this element and store the solution. */
20071 
20072  unsigned int i = 0;
20073  for(unsigned short j=0; j<volElem[l].nDOFsSol; ++j) {
20074 
20075  nLocalPoint++;
20076  const unsigned long globalIndex = volElem[l].offsetDOFsSolGlobal + j;
20077  globalID.push_back(globalIndex);
20078 
20079  for(unsigned short iVar=0; iVar<nVar_Consv; ++iVar, ++i) {
20080  DOFsSol.push_back(solDOFs[i]);
20081  }
20082  }
20083  }
20084  Buffer_Send_nPoint[0] = nLocalPoint;
20085 
20086  /*--- Each processor sends its local number of nodes to the master. ---*/
20087 
20088  if (rank == MASTER_NODE) Buffer_Recv_nPoint = new unsigned long[size];
20089 
20090 #ifdef HAVE_MPI
20091  SU2_MPI::Allreduce(&nLocalPoint, &MaxLocalPoint, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
20092  SU2_MPI::Gather(&Buffer_Send_nPoint, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nPoint, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
20093 #else
20094  MaxLocalPoint = nLocalPoint;
20095  Buffer_Recv_nPoint[0] = Buffer_Send_nPoint[0];
20096 #endif
20097 
20098  nBuffer_Scalar = MaxLocalPoint;
20099 
20100  /*--- Send and Recv buffers. ---*/
20101 
20102  su2double *Buffer_Send_Var = new su2double[MaxLocalPoint];
20103  su2double *Buffer_Recv_Var = NULL;
20104 
20105  unsigned long *Buffer_Send_GlobalIndex = new unsigned long[MaxLocalPoint];
20106  unsigned long *Buffer_Recv_GlobalIndex = NULL;
20107 
20108  /*--- Prepare the receive buffers in the master node only. ---*/
20109 
20110  if (rank == MASTER_NODE) {
20111 
20112  Buffer_Recv_Var = new su2double[size*MaxLocalPoint];
20113  Buffer_Recv_GlobalIndex = new unsigned long[size*MaxLocalPoint];
20114 
20115  /*--- Sum total number of nodes to be written and allocate arrays ---*/
20116  nGlobal_Poin = 0;
20117  for (iProcessor = 0; iProcessor < size; iProcessor++) {
20118  nGlobal_Poin += Buffer_Recv_nPoint[iProcessor];
20119  }
20120  Data = new su2double*[nVar_Total];
20121  for (iVar = 0; iVar < nVar_Total; iVar++) {
20122  Data[iVar] = new su2double[nGlobal_Poin];
20123  }
20124  }
20125 
20126  /*--- Main communication routine. Loop over each variable that has
20127  been requested by the user and perform the MPI comm. Temporary
20128  1-D buffers are used to send the solution for each variable at all
20129  nodes on each partition to the master node. These are then unpacked
20130  by the master and sorted by global index in one large n-dim. array. ---*/
20131 
20132  for (iVar = 0; iVar < nVar_Consv; iVar++) {
20133 
20134  /*--- Loop over this partition to collect the current variable ---*/
20135 
20136  jPoint = 0;
20137  for (iPoint = 0; iPoint < nLocalPoint; iPoint++) {
20138 
20139  /*--- Get this variable into the temporary send buffer. ---*/
20140 
20141  Buffer_Send_Var[jPoint] = DOFsSol[iPoint*nVar_Consv+iVar];
20142 
20143  /*--- Only send/recv the volumes & global indices during the first loop ---*/
20144 
20145  if (iVar == 0) {
20146  Buffer_Send_GlobalIndex[jPoint] = globalID[iPoint];
20147  }
20148 
20149  jPoint++;
20150 
20151  }
20152 
20153  /*--- Gather the data on the master node. ---*/
20154 
20155 #ifdef HAVE_MPI
20156  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
20157 #else
20158  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
20159 #endif
20160 
20161  if (iVar == 0) {
20162 #ifdef HAVE_MPI
20163  SU2_MPI::Gather(Buffer_Send_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
20164 #else
20165  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_GlobalIndex[iPoint] = Buffer_Send_GlobalIndex[iPoint];
20166 #endif
20167  }
20168 
20169  /*--- The master node unpacks and sorts this variable by global index ---*/
20170 
20171  if (rank == MASTER_NODE) {
20172  jPoint = 0;
20173  for (iProcessor = 0; iProcessor < size; iProcessor++) {
20174  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
20175 
20176  /*--- Get global index, then loop over each variable and store ---*/
20177 
20178  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
20179 
20180  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
20181 
20182  jPoint++;
20183 
20184  }
20185  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
20186  jPoint = (iProcessor+1)*nBuffer_Scalar;
20187  }
20188  }
20189 
20190  }
20191 
20192  /*--- Immediately release the temporary buffers. ---*/
20193 
20194  delete [] Buffer_Send_Var;
20195  delete [] Buffer_Send_GlobalIndex;
20196  if (rank == MASTER_NODE) {
20197  delete [] Buffer_Recv_nPoint;
20198  delete [] Buffer_Recv_Var;
20199  delete [] Buffer_Recv_GlobalIndex;
20200  }
20201 
20202 }
20203 
20204 void COutput::MergeBaselineSolution_FEM(CConfig *config, CGeometry *geometry, CSolver *solver, unsigned short val_iZone) {
20205 
20206  /*--- Local variables needed on all processors ---*/
20207  unsigned short iVar;
20208  unsigned long iPoint = 0, jPoint = 0;
20209 
20210  unsigned long Buffer_Send_nPoint[1], *Buffer_Recv_nPoint = NULL;
20211  unsigned long nLocalPoint = 0, MaxLocalPoint = 0;
20212  unsigned long iGlobal_Index = 0, nBuffer_Scalar = 0;
20213 
20214  int iProcessor;
20215 
20216  /*--- We know the number of fields from reading the restart. ---*/
20217 
20218  nVar_Total = config->fields.size() - 1;
20219 
20220  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
20221  geometrical information for the FEM DG solver. ---*/
20222  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
20223 
20224  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
20225  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
20226 
20227  /*--- Create the map from the global DOF ID to the local index. ---*/
20228  vector<su2double> DOFsSol;
20229  vector<unsigned long> globalID;
20230 
20231  /*--- Update the solution by looping over the owned volume elements. ---*/
20232  for(unsigned long l=0; l<nVolElemOwned; ++l) {
20233 
20234  /* Set the pointers for the residual and solution for this element. */
20235  const unsigned long offset = nVar_Total*volElem[l].offsetDOFsSolLocal;
20236  su2double *solDOFs = solver->GetVecSolDOFs() + offset;
20237 
20238  /* Loop over the DOFs for this element and store the solution. */
20239 
20240  unsigned int i = 0;
20241  for(unsigned short j=0; j<volElem[l].nDOFsSol; ++j) {
20242 
20243  nLocalPoint++;
20244  const unsigned long globalIndex = volElem[l].offsetDOFsSolGlobal + j;
20245  globalID.push_back(globalIndex);
20246 
20247  for(unsigned short iVar=0; iVar<nVar_Total; ++iVar, ++i) {
20248  DOFsSol.push_back(solDOFs[i]);
20249  }
20250  }
20251  }
20252  Buffer_Send_nPoint[0] = nLocalPoint;
20253 
20254  /*--- Each processor sends its local number of nodes to the master. ---*/
20255 
20256  if (rank == MASTER_NODE) Buffer_Recv_nPoint = new unsigned long[size];
20257 
20258 #ifdef HAVE_MPI
20259  SU2_MPI::Allreduce(&nLocalPoint, &MaxLocalPoint, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD);
20260  SU2_MPI::Gather(&Buffer_Send_nPoint, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nPoint, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
20261 #else
20262  MaxLocalPoint = nLocalPoint;
20263  Buffer_Recv_nPoint[0] = Buffer_Send_nPoint[0];
20264 #endif
20265 
20266  nBuffer_Scalar = MaxLocalPoint;
20267 
20268  /*--- Send and Recv buffers. ---*/
20269 
20270  su2double *Buffer_Send_Var = new su2double[MaxLocalPoint];
20271  su2double *Buffer_Recv_Var = NULL;
20272 
20273  unsigned long *Buffer_Send_GlobalIndex = new unsigned long[MaxLocalPoint];
20274  unsigned long *Buffer_Recv_GlobalIndex = NULL;
20275 
20276  /*--- Prepare the receive buffers in the master node only. ---*/
20277 
20278  if (rank == MASTER_NODE) {
20279 
20280  Buffer_Recv_Var = new su2double[size*MaxLocalPoint];
20281  Buffer_Recv_GlobalIndex = new unsigned long[size*MaxLocalPoint];
20282 
20283  /*--- Sum total number of nodes to be written and allocate arrays ---*/
20284  nGlobal_Poin = 0;
20285  for (iProcessor = 0; iProcessor < size; iProcessor++) {
20286  nGlobal_Poin += Buffer_Recv_nPoint[iProcessor];
20287  }
20288  Data = new su2double*[nVar_Total];
20289  for (iVar = 0; iVar < nVar_Total; iVar++) {
20290  Data[iVar] = new su2double[nGlobal_Poin];
20291  }
20292  }
20293 
20294  /*--- Main communication routine. Loop over each variable that has
20295  been requested by the user and perform the MPI comm. Temporary
20296  1-D buffers are used to send the solution for each variable at all
20297  nodes on each partition to the master node. These are then unpacked
20298  by the master and sorted by global index in one large n-dim. array. ---*/
20299 
20300  for (iVar = 0; iVar < nVar_Total; iVar++) {
20301 
20302  /*--- Loop over this partition to collect the current variable ---*/
20303 
20304  jPoint = 0;
20305  for (iPoint = 0; iPoint < nLocalPoint; iPoint++) {
20306 
20307  /*--- Get this variable into the temporary send buffer. ---*/
20308 
20309  Buffer_Send_Var[jPoint] = DOFsSol[iPoint*nVar_Total+iVar];
20310 
20311  /*--- Only send/recv the volumes & global indices during the first loop ---*/
20312 
20313  if (iVar == 0) {
20314  Buffer_Send_GlobalIndex[jPoint] = globalID[iPoint];
20315  }
20316 
20317  jPoint++;
20318 
20319  }
20320 
20321  /*--- Gather the data on the master node. ---*/
20322 
20323 #ifdef HAVE_MPI
20324  SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD);
20325 #else
20326  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint];
20327 #endif
20328 
20329  if (iVar == 0) {
20330 #ifdef HAVE_MPI
20331  SU2_MPI::Gather(Buffer_Send_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD);
20332 #else
20333  for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_GlobalIndex[iPoint] = Buffer_Send_GlobalIndex[iPoint];
20334 #endif
20335  }
20336 
20337  /*--- The master node unpacks and sorts this variable by global index ---*/
20338 
20339  if (rank == MASTER_NODE) {
20340  jPoint = 0;
20341  for (iProcessor = 0; iProcessor < size; iProcessor++) {
20342  for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) {
20343 
20344  /*--- Get global index, then loop over each variable and store ---*/
20345 
20346  iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint];
20347 
20348  Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint];
20349 
20350  jPoint++;
20351 
20352  }
20353  /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/
20354  jPoint = (iProcessor+1)*nBuffer_Scalar;
20355  }
20356  }
20357 
20358  }
20359 
20360  /*--- Immediately release the temporary buffers. ---*/
20361 
20362  delete [] Buffer_Send_Var;
20363  delete [] Buffer_Send_GlobalIndex;
20364  if (rank == MASTER_NODE) {
20365  delete [] Buffer_Recv_nPoint;
20366  delete [] Buffer_Recv_Var;
20367  delete [] Buffer_Recv_GlobalIndex;
20368  }
20369 
20370 }
20371 
20372 void COutput::SetResult_Files_FEM(CSolver ****solver_container, CGeometry ***geometry, CConfig **config,
20373  unsigned long iExtIter, unsigned short val_nZone) {
20374 
20375  unsigned short iZone;
20376 
20377  for (iZone = 0; iZone < val_nZone; iZone++) {
20378 
20379  /*--- Check whether we are writing any output at all. We can
20380  disable all output to avoid serial bottleneck at scale. ---*/
20381  if (config[iZone]->GetWrt_Output()) {
20382 
20383  /*--- Flags identifying the types of files to be written. ---*/
20384 
20385  bool Wrt_Vol = config[iZone]->GetWrt_Vol_Sol();
20386  bool Wrt_Srf = config[iZone]->GetWrt_Srf_Sol();
20387 
20388  /*--- Get the file output format ---*/
20389 
20390  unsigned short FileFormat = config[iZone]->GetOutput_FileFormat();
20391 
20392  /*--- Merge the node coordinates and connectivity, if necessary. This
20393  is only performed if a volume solution file is requested, and it
20394  is active by default. ---*/
20395 
20396  if (Wrt_Vol || Wrt_Srf) {
20397  if (rank == MASTER_NODE) cout << endl << "Merging connectivities in the Master node." << endl;
20398  MergeConnectivity_FEM(config[iZone], geometry[iZone][MESH_0], iZone);
20399  }
20400 
20401  /*--- Merge coordinates of all grid nodes (excluding ghost points).
20402  The grid coordinates are always merged and included first in the
20403  restart files. ---*/
20404 
20405  if (rank == MASTER_NODE) cout << "Merging coordinates in the Master node." << endl;
20406  MergeCoordinates_FEM(config[iZone], geometry[iZone][MESH_0]);
20407 
20408  if ((rank == MASTER_NODE) && (Wrt_Vol || Wrt_Srf)) {
20409  if (FileFormat == TECPLOT_BINARY) {
20410  if (rank == MASTER_NODE) cout << "Writing Tecplot binary volume and surface mesh files." << endl;
20411  SetTecplotBinary_DomainMesh(config[iZone], geometry[iZone][MESH_0], iZone);
20412  SetTecplotBinary_SurfaceMesh(config[iZone], geometry[iZone][MESH_0], iZone);
20413  }
20414  }
20415 
20416  /*--- Merge the solution data needed for volume solutions and restarts ---*/
20417 
20418  if (rank == MASTER_NODE) cout << "Merging solution in the Master node." << endl;
20419  MergeSolution_FEM(config[iZone], geometry[iZone][MESH_0], solver_container[iZone][MESH_0], iZone);
20420 
20421  /*--- Write restart, or Tecplot files using the merged data.
20422  This data lives only on the master, and these routines are currently
20423  executed by the master proc alone (as if in serial). ---*/
20424 
20425  if (rank == MASTER_NODE) {
20426 
20427  /*--- Write a native restart file ---*/
20428 
20429  if (rank == MASTER_NODE) cout << "Writing SU2 native restart file." << endl;
20430  SetRestart(config[iZone], geometry[iZone][MESH_0], solver_container[iZone][MESH_0] , iZone);
20431 
20432  if (Wrt_Vol) {
20433 
20434  switch (FileFormat) {
20435 
20436  case TECPLOT:
20437 
20438  /*--- Write a Tecplot ASCII file ---*/
20439 
20440  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file volume solution file." << endl;
20441  SetTecplotASCII(config[iZone], geometry[iZone][MESH_0], solver_container[iZone][MESH_0], iZone, val_nZone, false);
20442  DeallocateConnectivity(config[iZone], geometry[iZone][MESH_0], false);
20443  break;
20444 
20445  case FIELDVIEW:
20446 
20447  /*--- Write a FieldView ASCII file ---*/
20448 
20449  if (rank == MASTER_NODE) cout << "Writing FieldView ASCII file volume solution file." << endl;
20450  SetFieldViewASCII(config[iZone], geometry[iZone][MESH_0], iZone, val_nZone);
20451  DeallocateConnectivity(config[iZone], geometry[iZone][MESH_0], false);
20452  break;
20453 
20454  case TECPLOT_BINARY:
20455 
20456  /*--- Write a Tecplot binary solution file ---*/
20457 
20458  if (rank == MASTER_NODE) cout << "Writing Tecplot binary volume solution file." << endl;
20459  SetTecplotBinary_DomainSolution(config[iZone], geometry[iZone][MESH_0], iZone);
20460  DeallocateConnectivity(config[iZone], geometry[iZone][MESH_0], false);
20461  break;
20462 
20463  case FIELDVIEW_BINARY:
20464 
20465  /*--- Write a FieldView binary file ---*/
20466 
20467  if (rank == MASTER_NODE) cout << "Writing FieldView binary file volume solution file." << endl;
20468  SetFieldViewBinary(config[iZone], geometry[iZone][MESH_0], iZone, val_nZone);
20469  DeallocateConnectivity(config[iZone], geometry[iZone][MESH_0], false);
20470  break;
20471 
20472  case PARAVIEW:
20473 
20474  /*--- Write a Paraview ASCII file ---*/
20475 
20476  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII volume solution file." << endl;
20477  SetParaview_ASCII(config[iZone], geometry[iZone][MESH_0], iZone, val_nZone, false);
20478  DeallocateConnectivity(config[iZone], geometry[iZone][MESH_0], false);
20479  break;
20480 
20481  default:
20482  break;
20483  }
20484 
20485  }
20486 
20487  if (Wrt_Srf) {
20488 
20489  switch (FileFormat) {
20490 
20491  case TECPLOT:
20492 
20493  /*--- Write a Tecplot ASCII file ---*/
20494 
20495  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII surface solution file." << endl;
20496  SetTecplotASCII(config[iZone], geometry[iZone][MESH_0], solver_container[iZone][MESH_0] , iZone, val_nZone, true);
20497  DeallocateConnectivity(config[iZone], geometry[iZone][MESH_0], true);
20498  break;
20499 
20500  case TECPLOT_BINARY:
20501 
20502  /*--- Write a Tecplot binary solution file ---*/
20503 
20504  if (rank == MASTER_NODE) cout << "Writing Tecplot binary surface solution file." << endl;
20505  SetTecplotBinary_SurfaceSolution(config[iZone], geometry[iZone][MESH_0], iZone);
20506  DeallocateConnectivity(config[iZone], geometry[iZone][MESH_0], true);
20507  break;
20508 
20509  case PARAVIEW:
20510 
20511  /*--- Write a Paraview ASCII file ---*/
20512 
20513  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII surface solution file." << endl;
20514  SetParaview_ASCII(config[iZone], geometry[iZone][MESH_0], iZone, val_nZone, true);
20515  DeallocateConnectivity(config[iZone], geometry[iZone][MESH_0], true);
20516  break;
20517 
20518  default:
20519  break;
20520  }
20521 
20522  }
20523 
20524  /*--- Release memory needed for merging the solution data. ---*/
20525 
20526  DeallocateCoordinates(config[iZone], geometry[iZone][MESH_0]);
20527  DeallocateSolution(config[iZone], geometry[iZone][MESH_0]);
20528 
20529  }
20530 
20531  /*--- Final broadcast (informing other procs that the base output
20532  file was written). ---*/
20533 
20534 #ifdef HAVE_MPI
20537 #endif
20538 
20539  } else {
20540  if (rank == MASTER_NODE) cout << endl << "Restart and solution output disabled." << endl;
20541  }
20542  }
20543 }
20544 
20545 void COutput::SetBaselineResult_Files_FEM(CSolver ***solver, CGeometry ***geometry, CConfig **config,
20546  unsigned long iExtIter, unsigned short val_nZone) {
20547 
20548  unsigned short iZone, iInst, nInst;
20549 
20550  for (iZone = 0; iZone < val_nZone; iZone++) {
20551 
20552  nInst = config[iZone]->GetnTimeInstances();
20553 
20554  for (iInst = 0; iInst < nInst; iInst++) {
20555 
20556  config[iZone]->SetiInst(iInst);
20557 
20558  /*--- Flags identifying the types of files to be written. ---*/
20559 
20560  bool Wrt_Vol = config[iZone]->GetWrt_Vol_Sol();
20561  bool Wrt_Srf = config[iZone]->GetWrt_Srf_Sol();
20562 
20563  /*--- Get the file output format ---*/
20564 
20565  unsigned short FileFormat = config[iZone]->GetOutput_FileFormat();
20566 
20567  /*--- Merge the node coordinates and connectivity if necessary. This
20568  is only performed if a volume solution file is requested, and it
20569  is active by default. ---*/
20570 
20571  if ((Wrt_Vol || Wrt_Srf)) {
20572  if (rank == MASTER_NODE) cout << "Merging connectivities in the Master node." << endl;
20573  MergeConnectivity_FEM(config[iZone], geometry[iZone][iInst], iZone);
20574  }
20575 
20576  /*--- Merge the solution data needed for volume solutions and restarts ---*/
20577 
20578  if ((Wrt_Vol || Wrt_Srf)) {
20579  if (rank == MASTER_NODE) cout << "Merging solution in the Master node." << endl;
20580  MergeBaselineSolution_FEM(config[iZone], geometry[iZone][iInst], solver[iZone][iInst], iZone);
20581  }
20582 
20583  /*--- Write restart, Tecplot or Paraview files using the merged data.
20584  This data lives only on the master, and these routines are currently
20585  executed by the master proc alone (as if in serial). ---*/
20586 
20587  if (rank == MASTER_NODE) {
20588 
20589  if (Wrt_Vol) {
20590 
20591  switch (FileFormat) {
20592 
20593  case TECPLOT:
20594 
20595  /*--- Write a Tecplot ASCII file ---*/
20596 
20597  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file (volume grid)." << endl;
20598  SetTecplotASCII(config[iZone], geometry[iZone][iInst], &solver[iZone][iInst], iZone, val_nZone, false);
20599  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
20600  break;
20601 
20602  case FIELDVIEW:
20603 
20604  /*--- Write a FieldView ASCII file ---*/
20605 
20606  if (rank == MASTER_NODE) cout << "Writing FieldView ASCII file (volume grid)." << endl;
20607  SetFieldViewASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone);
20608  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
20609  break;
20610 
20611  case TECPLOT_BINARY:
20612 
20613  /*--- Write a Tecplot binary solution file ---*/
20614 
20615  if (rank == MASTER_NODE) cout << "Writing Tecplot Binary file (volume grid)." << endl;
20616  SetTecplotBinary_DomainMesh(config[iZone], geometry[iZone][iInst], iZone);
20617  SetTecplotBinary_DomainSolution(config[iZone], geometry[iZone][iInst], iZone);
20618  break;
20619 
20620  case FIELDVIEW_BINARY:
20621 
20622  /*--- Write a binary binary file ---*/
20623 
20624  if (rank == MASTER_NODE) cout << "Writing FieldView ASCII file (volume grid)." << endl;
20625  SetFieldViewBinary(config[iZone], geometry[iZone][iInst], iZone, val_nZone);
20626  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
20627  break;
20628 
20629  case PARAVIEW:
20630 
20631  /*--- Write a Paraview ASCII file ---*/
20632 
20633  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII file (volume grid)." << endl;
20634  SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, false);
20635  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
20636  break;
20637 
20638  default:
20639  break;
20640  }
20641 
20642  }
20643 
20644  if (Wrt_Srf) {
20645 
20646  switch (FileFormat) {
20647 
20648  case TECPLOT:
20649 
20650  /*--- Write a Tecplot ASCII file ---*/
20651 
20652  if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file (surface grid)." << endl;
20653  SetTecplotASCII(config[iZone], geometry[iZone][iInst], &solver[iZone][iInst], iZone, val_nZone, true);
20654  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], true);
20655  break;
20656 
20657  case TECPLOT_BINARY:
20658 
20659  /*--- Write a Tecplot binary solution file ---*/
20660 
20661  if (rank == MASTER_NODE) cout << "Writing Tecplot Binary file (surface grid)." << endl;
20662  SetTecplotBinary_SurfaceMesh(config[iZone], geometry[iZone][iInst], iZone);
20663  SetTecplotBinary_SurfaceSolution(config[iZone], geometry[iZone][iInst], iZone);
20664  break;
20665 
20666  case PARAVIEW:
20667 
20668  /*--- Write a Paraview ASCII file ---*/
20669 
20670  if (rank == MASTER_NODE) cout << "Writing Paraview ASCII file (surface grid)." << endl;
20671  SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, true);
20672  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], true);
20673  break;
20674 
20675  default:
20676  break;
20677  }
20678  }
20679 
20680  if (FileFormat == TECPLOT_BINARY) {
20681  if (!wrote_base_file)
20682  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false);
20683  if (!wrote_surf_file)
20684  DeallocateConnectivity(config[iZone], geometry[iZone][iInst], wrote_surf_file);
20685  }
20686 
20687  if (Wrt_Vol || Wrt_Srf)
20688  DeallocateSolution(config[iZone], geometry[iZone][iInst]);
20689  }
20690 
20691  /*--- Final broadcast (informing other procs that the base output
20692  file was written). ---*/
20693 
20694 #ifdef HAVE_MPI
20696 #endif
20697  }
20698  }
20699 }
20700 
20701 void COutput::LoadLocalData_FEM(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) {
20702 
20703  unsigned short iDim;
20704  unsigned short Kind_Solver = config->GetKind_Solver();
20705  unsigned short nDim = geometry->GetnDim();
20706 
20707  unsigned long iVar, jVar;
20708  unsigned long iPoint, jPoint, FirstIndex = NONE, SecondIndex = NONE;
20709  unsigned long nVar_First = 0, nVar_Second = 0, nVar_Consv_Par = 0;
20710 
20711  stringstream varname;
20712 
20713  /*--- Use a switch statement to decide how many solver containers we have
20714  in this zone for output. ---*/
20715 
20716  switch (Kind_Solver) {
20717  case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_LES: FirstIndex = FLOW_SOL; SecondIndex = NONE; break;
20718  case FEM_RANS : FirstIndex = FLOW_SOL; SecondIndex = TURB_SOL; break;
20719  default: SecondIndex = NONE; break;
20720  }
20721 
20722  nVar_First = solver[FirstIndex]->GetnVar();
20723  if (SecondIndex != NONE) nVar_Second = solver[SecondIndex]->GetnVar();
20724  nVar_Consv_Par = nVar_First + nVar_Second;
20725 
20726  /*--------------------------------------------------------------------------*/
20727  /*--- Step 1: Register the variables that will be output. To register a ---*/
20728  /*--- variable, two things are required. First, increment the ---*/
20729  /*--- counter for the number of variables (nVar_Par), which ---*/
20730  /*--- controls the size of the data structure allocation, i.e., ---*/
20731  /*--- the number of columns in an nPoint x nVar structure. ---*/
20732  /*--- Second, add a name for the variable to the vector that ---*/
20733  /*--- holds the string names. ---*/
20734  /*--------------------------------------------------------------------------*/
20735 
20736  /*--- All output files first need the grid coordinates. ---*/
20737 
20738  nVar_Par = 1; Variable_Names.push_back("x");
20739  nVar_Par += 1; Variable_Names.push_back("y");
20740  if (geometry->GetnDim() == 3) {
20741  nVar_Par += 1; Variable_Names.push_back("z");
20742  }
20743 
20744  /*--- At a mininum, the restarts and visualization files need the
20745  conservative variables, so these follow next. ---*/
20746 
20747  nVar_Par += nVar_Consv_Par;
20748 
20749  Variable_Names.push_back("Density");
20750  Variable_Names.push_back("X-Momentum");
20751  Variable_Names.push_back("Y-Momentum");
20752  if (geometry->GetnDim() == 3) Variable_Names.push_back("Z-Momentum");
20753  Variable_Names.push_back("Energy");
20754 
20755  /*--- Eventually, turbulence model from second container goes here. ---*/
20756 
20757  if (!config->GetLow_MemoryOutput()) {
20758 
20759  /*--- Add Pressure, Temperature, Cp, Mach. ---*/
20760 
20761  nVar_Par += 1;
20762  Variable_Names.push_back("Pressure");
20763 
20764  nVar_Par += 3;
20765  Variable_Names.push_back("Temperature");
20766  if (config->GetOutput_FileFormat() == PARAVIEW){
20767  Variable_Names.push_back("Pressure_Coefficient");
20768  } else {
20769  Variable_Names.push_back("C<sub>p</sub>");
20770  }
20771  Variable_Names.push_back("Mach");
20772 
20773  /*--- New variables get registered here before the end of the loop. ---*/
20774 
20775  if (Kind_Solver == FEM_NAVIER_STOKES){
20776  nVar_Par += 1;
20777  Variable_Names.push_back("Laminar_Viscosity");
20778  }
20779  if ((Kind_Solver == FEM_LES) && (config->GetKind_SGS_Model() != IMPLICIT_LES)){
20780  nVar_Par += 1;
20781  Variable_Names.push_back("Eddy_Viscosity");
20782  }
20783  }
20784 
20785  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
20786  geometrical information for the FEM DG solver. ---*/
20787 
20788  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
20789 
20790  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
20791  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
20792 
20793  /*--- Get a pointer to the fluid model class from the DG-FEM solver
20794  so that we can access the states below. ---*/
20795 
20796  CFluidModel *DGFluidModel = solver[FLOW_SOL]->GetFluidModel();
20797 
20798  /*--- Allocate the local data structure now that we know how many
20799  variables are in the output. ---*/
20800 
20801  Local_Data = new su2double*[nLocalPoint_Sort];
20802  for (iPoint = 0; iPoint < nLocalPoint_Sort; iPoint++) {
20803  Local_Data[iPoint] = new su2double[nVar_Par];
20804  }
20805 
20806  /*--------------------------------------------------------------------------*/
20807  /*--- Step 2: Loop over all grid nodes and load up the desired data for ---*/
20808  /*--- the restart and vizualization files. Note that we need to ---*/
20809  /*--- increment the iVar variable after each variable load. ---*/
20810  /*--- The idea is that we're filling up the columns of field ---*/
20811  /*--- data for each iPoint (row) of the data structure. ---*/
20812  /*--- This data will then be sorted, communicated, and written ---*/
20813  /*--- to files automatically after this routine. Note that the ---*/
20814  /*--- ordering of the data loading MUST match the order of the ---*/
20815  /*--- variable registration above for the files to be correct. ---*/
20816  /*--------------------------------------------------------------------------*/
20817 
20818  jPoint = 0;
20819 
20820  /*--- Access the solution by looping over the owned volume elements. ---*/
20821 
20822  for(unsigned long l=0; l<nVolElemOwned; ++l) {
20823 
20824  /* Set the pointers for the solution for this element. */
20825 
20826  const unsigned long offset = nVar_First*volElem[l].offsetDOFsSolLocal;
20827  su2double *solDOFs = solver[FirstIndex]->GetVecSolDOFs() + offset;
20828 
20829  for(unsigned short j=0; j<volElem[l].nDOFsSol; ++j) {
20830 
20831  /*--- Restart the column index with each new point. ---*/
20832 
20833  iVar = 0;
20834 
20835  /*--- Get the conservative variables for this particular DOF. ---*/
20836 
20837  const su2double *U = solDOFs + j*nVar_First;
20838 
20839  /*--- Load the coordinate values of the solution DOFs. ---*/
20840 
20841  const su2double *coor = volElem[l].coorSolDOFs.data() + j*nDim;
20842  for(unsigned short k=0; k<nDim; ++k) {
20843  Local_Data[jPoint][iVar] = coor[k];
20844  iVar++;
20845  }
20846 
20847  /* Load the conservative variables. */
20848 
20849  for(jVar=0; jVar < nVar_First; ++jVar) {
20850  Local_Data[jPoint][iVar] = U[jVar];
20851  iVar++;
20852  }
20853 
20854  /*--- Prepare the primitive states. ---*/
20855 
20856  const su2double DensityInv = 1.0/U[0];
20857  su2double vel[3], Velocity2 = 0.0;
20858  for(iDim=0; iDim<nDim; ++iDim) {
20859  vel[iDim] = U[iDim+1]*DensityInv;
20860  Velocity2 += vel[iDim]*vel[iDim];
20861  }
20862  su2double StaticEnergy = U[nDim+1]*DensityInv - 0.5*Velocity2;
20863  DGFluidModel->SetTDState_rhoe(U[0], StaticEnergy);
20864 
20865  /*--- Load data for the pressure, temperature, Cp, and Mach variables. ---*/
20866 
20867  Local_Data[jPoint][iVar] = DGFluidModel->GetPressure(); iVar++;
20868  Local_Data[jPoint][iVar] = DGFluidModel->GetTemperature(); iVar++;
20869  Local_Data[jPoint][iVar] = DGFluidModel->GetCp(); iVar++;
20870  Local_Data[jPoint][iVar] = sqrt(Velocity2)/DGFluidModel->GetSoundSpeed(); iVar++;
20871 
20872  /*--- New variables can be loaded to the Local_Data structure here,
20873  assuming they were registered above correctly. ---*/
20874 
20875  if (Kind_Solver == FEM_NAVIER_STOKES){
20876  Local_Data[jPoint][iVar] = DGFluidModel->GetLaminarViscosity(); iVar++;
20877  }
20878  if ((Kind_Solver == FEM_LES) && (config->GetKind_SGS_Model() != IMPLICIT_LES)){
20879  // todo: Export Eddy instead of Laminar viscosity
20880  Local_Data[jPoint][iVar] = DGFluidModel->GetLaminarViscosity(); iVar++;
20881  }
20882 
20883  /*--- Increment the point counter. ---*/
20884 
20885  jPoint++;
20886  }
20887  }
20888 
20889 }
20890 
20891 void COutput::PrepareOffsets(CConfig *config, CGeometry *geometry) {
20892 
20893  unsigned long iPoint;
20894 
20895  /*--- Bool to distinguish between the FVM and FEM solvers. ---*/
20896 
20897  unsigned short KindSolver = config->GetKind_Solver();
20898  bool fem_solver = ((KindSolver == FEM_EULER) ||
20899  (KindSolver == FEM_NAVIER_STOKES) ||
20900  (KindSolver == FEM_RANS) ||
20901  (KindSolver == FEM_LES));
20902 
20903  /*--- Reset point sorting counters ---*/
20904 
20905  nGlobalPoint_Sort = 0;
20906  nLocalPoint_Sort = 0;
20907 
20908  /*--- Prepare the offsets for the FV solver ---*/
20909 
20910  if (!fem_solver) {
20911 
20912  /*--- Search all send/recv boundaries on this partition for any periodic
20913  nodes that were part of the original domain. We want to recover these
20914  for visualization purposes. ---*/
20915 
20916  unsigned long iVertex;
20917  bool isPeriodic;
20918 
20919  Local_Halo_Sort = new int[geometry->GetnPoint()];
20920  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
20921  Local_Halo_Sort[iPoint] = !geometry->node[iPoint]->GetDomain();
20922 
20923  for (unsigned short iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
20924  if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) {
20925 
20926  /*--- Checking for less than or equal to the rank, because there may
20927  be some periodic halo nodes that send info to the same rank. ---*/
20928 
20929  for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
20930  iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
20931  isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) &&
20932  (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1));
20933  if (isPeriodic) Local_Halo_Sort[iPoint] = false;
20934  }
20935  }
20936  }
20937 
20938  /*--- Sum total number of nodes that belong to the domain ---*/
20939 
20940  for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++)
20941  if (Local_Halo_Sort[iPoint] == false)
20942  nLocalPoint_Sort++;
20943 
20944 #ifdef HAVE_MPI
20945  SU2_MPI::Allreduce(&nLocalPoint_Sort, &nGlobalPoint_Sort, 1,
20947 #else
20948  nGlobalPoint_Sort = nLocalPoint_Sort;
20949 #endif
20950 
20951  /*--- Set a final variable for the number of points in the restart
20952  file. We do not write the periodic points for the FV solver, even if
20953  they show up in the viz. files. ---*/
20954 
20955  nPoint_Restart = geometry->GetGlobal_nPointDomain();
20956 
20957  } else {
20958 
20959  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
20960  geometrical information for the FEM DG solver. ---*/
20961 
20962  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
20963 
20964  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
20965  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
20966 
20967  /*--- Update the solution by looping over the owned volume elements. ---*/
20968 
20969  for(unsigned long l=0; l<nVolElemOwned; ++l) {
20970 
20971  /* Count up the number of local points we have for allocating storage. */
20972 
20973  for(unsigned short j=0; j<volElem[l].nDOFsSol; ++j) {
20974  nLocalPoint_Sort++;
20975  }
20976  }
20977 
20978  Local_Halo_Sort = new int[nLocalPoint_Sort];
20979  for (iPoint = 0; iPoint < nLocalPoint_Sort; iPoint++)
20980  Local_Halo_Sort[iPoint] = false;
20981 
20982 #ifdef HAVE_MPI
20983  SU2_MPI::Allreduce(&nLocalPoint_Sort, &nGlobalPoint_Sort, 1,
20985 #else
20986  nGlobalPoint_Sort = nLocalPoint_Sort;
20987 #endif
20988 
20989  /*--- Set a final variable for the number of points in the restart
20990  file. We do not write the periodic points for the FV solver, even if
20991  they show up in the viz. files. ---*/
20992 
20993  nPoint_Restart = nGlobalPoint_Sort;
20994 
20995  }
20996 
20997  /*--- Now that we know the actual number of points we need to output,
20998  compute the number of points that will be on each processor.
20999  This is a linear partitioning with the addition of a simple load
21000  balancing for any remainder points. ---*/
21001 
21002  beg_node = new unsigned long[size];
21003  end_node = new unsigned long[size];
21004 
21005  nPoint_Lin = new unsigned long[size];
21006  nPoint_Cum = new unsigned long[size+1];
21007 
21008  unsigned long total_points = 0;
21009  for (int ii = 0; ii < size; ii++) {
21010  nPoint_Lin[ii] = nGlobalPoint_Sort/size;
21011  total_points += nPoint_Lin[ii];
21012  }
21013 
21014  /*--- Get the number of remainder points after the even division. ---*/
21015 
21016  unsigned long remainder = nGlobalPoint_Sort - total_points;
21017  for (unsigned long ii = 0; ii < remainder; ii++) {
21018  nPoint_Lin[ii]++;
21019  }
21020 
21021  /*--- Store the local number of nodes on each proc in the linear
21022  partitioning, the beginning/end index, and the linear partitioning
21023  within an array in cumulative storage format. ---*/
21024 
21025  beg_node[0] = 0;
21026  end_node[0] = beg_node[0] + nPoint_Lin[0];
21027  nPoint_Cum[0] = 0;
21028  for (int ii = 1; ii < size; ii++) {
21029  beg_node[ii] = end_node[ii-1];
21030  end_node[ii] = beg_node[ii] + nPoint_Lin[ii];
21031  nPoint_Cum[ii] = nPoint_Cum[ii-1] + nPoint_Lin[ii-1];
21032  }
21033  nPoint_Cum[size] = nGlobalPoint_Sort;
21034 
21035 }
21036 
21037 void COutput::SortConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short val_iZone) {
21038 
21039  /*--- Flags identifying the types of files to be written. ---*/
21040 
21041  bool Wrt_Vol = config->GetWrt_Vol_Sol();
21042  bool Wrt_Srf = config->GetWrt_Srf_Sol();
21043 
21044  /*--- Sort connectivity for each type of element (excluding halos). Note
21045  In these routines, we sort the connectivity into a linear partitioning
21046  across all processors based on the global index of the grid nodes. ---*/
21047 
21048  /*--- Sort volumetric grid connectivity. ---*/
21049 
21050  if (Wrt_Vol) {
21051 
21052  if ((rank == MASTER_NODE) && (size != SINGLE_NODE))
21053  cout <<"Sorting volumetric grid connectivity." << endl;
21054 
21055  SortVolumetricConnectivity_FEM(config, geometry, TRIANGLE );
21056  SortVolumetricConnectivity_FEM(config, geometry, QUADRILATERAL);
21057  SortVolumetricConnectivity_FEM(config, geometry, TETRAHEDRON );
21058  SortVolumetricConnectivity_FEM(config, geometry, HEXAHEDRON );
21059  SortVolumetricConnectivity_FEM(config, geometry, PRISM );
21060  SortVolumetricConnectivity_FEM(config, geometry, PYRAMID );
21061 
21062  }
21063 
21064  /*--- Sort surface grid connectivity. ---*/
21065 
21066  if (Wrt_Srf) {
21067 
21068  if ((rank == MASTER_NODE) && (size != SINGLE_NODE))
21069  cout <<"Sorting surface grid connectivity." << endl;
21070 
21071  SortSurfaceConnectivity_FEM(config, geometry, LINE );
21072  SortSurfaceConnectivity_FEM(config, geometry, TRIANGLE );
21073  SortSurfaceConnectivity_FEM(config, geometry, QUADRILATERAL);
21074 
21075  }
21076 
21077  /*--- Reduce the total number of cells we will be writing in the output files. ---*/
21078 
21079  unsigned long nTotal_Elem = nParallel_Tria + nParallel_Quad + nParallel_Tetr + nParallel_Hexa + nParallel_Pris + nParallel_Pyra;
21080  unsigned long nTotal_Surf_Elem = nParallel_Line + nParallel_BoundTria + nParallel_BoundQuad;
21081 #ifndef HAVE_MPI
21082  nGlobal_Elem_Par = nTotal_Elem;
21083  nSurf_Elem_Par = nTotal_Surf_Elem;
21084 #else
21085  SU2_MPI::Allreduce(&nTotal_Elem, &nGlobal_Elem_Par, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
21086  SU2_MPI::Allreduce(&nTotal_Surf_Elem, &nSurf_Elem_Par, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
21087 #endif
21088 
21089 }
21090 
21091 void COutput::SortVolumetricConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) {
21092 
21093 }
21094 
21095 void COutput::SortSurfaceConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) {
21096 
21097 }
21098 
21100 
21101  unsigned long iProcessor;
21102  unsigned long iPoint, Global_Index;
21103 
21104  /* For convenience, set the total number of variables stored at each DOF. */
21105 
21106  int VARS_PER_POINT = nVar_Par;
21107 
21108 #ifdef HAVE_MPI
21109  SU2_MPI::Request *send_req, *recv_req;
21110  SU2_MPI::Status status;
21111  int ind;
21112 #endif
21113 
21114  /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
21115  geometrical information for the FEM DG solver. ---*/
21116 
21117  CMeshFEM_DG *DGGeometry = dynamic_cast<CMeshFEM_DG *>(geometry);
21118 
21119  unsigned long nVolElemOwned = DGGeometry->GetNVolElemOwned();
21120  CVolumeElementFEM *volElem = DGGeometry->GetVolElem();
21121 
21122  /*--- Create the map from the global DOF ID to the local index. ---*/
21123 
21124  //map<unsigned long, unsigned long> mapLocal2Global;
21125  vector<unsigned long> globalID;
21126 
21127  /*--- Update the solution by looping over the owned volume elements. ---*/
21128  for(unsigned long l=0; l<nVolElemOwned; ++l) {
21129 
21130  /* Loop over the DOFs for this element and store the solution. */
21131  for(unsigned short j=0; j<volElem[l].nDOFsSol; ++j) {
21132  const unsigned long globalIndex = volElem[l].offsetDOFsSolGlobal + j;
21133  globalID.push_back(globalIndex);
21134  }
21135  }
21136 
21137  /*--- We start with the grid nodes distributed across all procs with
21138  no particular ordering assumed. We need to loop through our local partition
21139  and decide how many nodes we must send to each other rank in order to
21140  have all nodes sorted according to a linear partitioning of the grid
21141  nodes, i.e., rank 0 holds the first ~ nGlobalPoint()/nProcessors nodes.
21142  First, initialize a counter and flag. ---*/
21143 
21144  int *nPoint_Send = new int[size+1]; nPoint_Send[0] = 0;
21145  int *nPoint_Recv = new int[size+1]; nPoint_Recv[0] = 0;
21146  int *nPoint_Flag = new int[size];
21147 
21148  for (int ii=0; ii < size; ii++) {
21149  nPoint_Send[ii] = 0;
21150  nPoint_Recv[ii] = 0;
21151  nPoint_Flag[ii]= -1;
21152  }
21153  nPoint_Send[size] = 0; nPoint_Recv[size] = 0;
21154 
21155  for (iPoint = 0; iPoint < nLocalPoint_Sort; iPoint++ ) {
21156 
21157  /*--- Get the global index of the current point. ---*/
21158 
21159  Global_Index = globalID[iPoint];
21160 
21161  /*--- Search for the processor that owns this point ---*/
21162 
21163  iProcessor = Global_Index/nPoint_Lin[0];
21164  if (iProcessor >= (unsigned long)size)
21165  iProcessor = (unsigned long)size-1;
21166  if (Global_Index >= nPoint_Cum[iProcessor])
21167  while(Global_Index >= nPoint_Cum[iProcessor+1]) iProcessor++;
21168  else
21169  while(Global_Index < nPoint_Cum[iProcessor]) iProcessor--;
21170 
21171  /*--- If we have not visted this node yet, increment our
21172  number of elements that must be sent to a particular proc. ---*/
21173 
21174  if (nPoint_Flag[iProcessor] != (int)iPoint) {
21175  nPoint_Flag[iProcessor] = (int)iPoint;
21176  nPoint_Send[iProcessor+1]++;
21177  }
21178 
21179  }
21180 
21181  /*--- Communicate the number of nodes to be sent/recv'd amongst
21182  all processors. After this communication, each proc knows how
21183  many cells it will receive from each other processor. ---*/
21184 
21185 #ifdef HAVE_MPI
21186  SU2_MPI::Alltoall(&(nPoint_Send[1]), 1, MPI_INT,
21187  &(nPoint_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD);
21188 #else
21189  nPoint_Recv[1] = nPoint_Send[1];
21190 #endif
21191 
21192  /*--- Prepare to send coordinates. First check how many
21193  messages we will be sending and receiving. Here we also put
21194  the counters into cumulative storage format to make the
21195  communications simpler. ---*/
21196 
21197  int nSends = 0, nRecvs = 0;
21198  for (int ii=0; ii < size; ii++) nPoint_Flag[ii] = -1;
21199 
21200  for (int ii = 0; ii < size; ii++) {
21201  if ((ii != rank) && (nPoint_Send[ii+1] > 0)) nSends++;
21202  if ((ii != rank) && (nPoint_Recv[ii+1] > 0)) nRecvs++;
21203 
21204  nPoint_Send[ii+1] += nPoint_Send[ii];
21205  nPoint_Recv[ii+1] += nPoint_Recv[ii];
21206  }
21207 
21208  /*--- Allocate memory to hold the connectivity that we are sending. ---*/
21209 
21210  su2double *connSend = NULL;
21211  connSend = new su2double[VARS_PER_POINT*nPoint_Send[size]];
21212  for (int ii = 0; ii < VARS_PER_POINT*nPoint_Send[size]; ii++)
21213  connSend[ii] = 0;
21214 
21215  /*--- Allocate arrays for sending the global ID. ---*/
21216 
21217  unsigned long *idSend = new unsigned long[nPoint_Send[size]];
21218  for (int ii = 0; ii < nPoint_Send[size]; ii++)
21219  idSend[ii] = 0;
21220 
21221  /*--- Create an index variable to keep track of our index
21222  positions as we load up the send buffer. ---*/
21223 
21224  unsigned long *index = new unsigned long[size];
21225  for (int ii=0; ii < size; ii++) index[ii] = VARS_PER_POINT*nPoint_Send[ii];
21226 
21227  unsigned long *idIndex = new unsigned long[size];
21228  for (int ii=0; ii < size; ii++) idIndex[ii] = nPoint_Send[ii];
21229 
21230  /*--- Loop through our elements and load the elems and their
21231  additional data that we will send to the other procs. ---*/
21232 
21233  for (iPoint = 0; iPoint < nLocalPoint_Sort; iPoint++) {
21234 
21235  /*--- Get the index of the current point. ---*/
21236 
21237  Global_Index = globalID[iPoint];
21238 
21239  /*--- Search for the processor that owns this point. ---*/
21240 
21241  iProcessor = Global_Index/nPoint_Lin[0];
21242  if (iProcessor >= (unsigned long)size)
21243  iProcessor = (unsigned long)size-1;
21244  if (Global_Index >= nPoint_Cum[iProcessor])
21245  while(Global_Index >= nPoint_Cum[iProcessor+1]) iProcessor++;
21246  else
21247  while(Global_Index < nPoint_Cum[iProcessor]) iProcessor--;
21248 
21249  /*--- Load data into the buffer for sending. ---*/
21250 
21251  if (nPoint_Flag[iProcessor] != (int)iPoint) {
21252 
21253  nPoint_Flag[iProcessor] = (int)iPoint;
21254  unsigned long nn = index[iProcessor];
21255 
21256  /*--- Load the data values. ---*/
21257 
21258  for (unsigned short kk = 0; kk < VARS_PER_POINT; kk++) {
21259  connSend[nn] = Local_Data[iPoint][kk]; nn++;
21260  }
21261 
21262  /*--- Load the global ID (minus offset) for sorting the
21263  points once they all reach the correct processor. ---*/
21264 
21265  nn = idIndex[iProcessor];
21266  idSend[nn] = Global_Index - beg_node[iProcessor];
21267 
21268  /*--- Increment the index by the message length ---*/
21269 
21270  index[iProcessor] += VARS_PER_POINT;
21271  idIndex[iProcessor]++;
21272 
21273  }
21274 
21275  }
21276 
21277  /*--- Free memory after loading up the send buffer. ---*/
21278 
21279  delete [] index;
21280  delete [] idIndex;
21281 
21282  /*--- Allocate the memory that we need for receiving the conn
21283  values and then cue up the non-blocking receives. Note that
21284  we do not include our own rank in the communications. We will
21285  directly copy our own data later. ---*/
21286 
21287  su2double *connRecv = NULL;
21288  connRecv = new su2double[VARS_PER_POINT*nPoint_Recv[size]];
21289  for (int ii = 0; ii < VARS_PER_POINT*nPoint_Recv[size]; ii++)
21290  connRecv[ii] = 0;
21291 
21292  unsigned long *idRecv = new unsigned long[nPoint_Recv[size]];
21293  for (int ii = 0; ii < nPoint_Recv[size]; ii++)
21294  idRecv[ii] = 0;
21295 
21296 #ifdef HAVE_MPI
21297  /*--- We need double the number of messages to send both the conn.
21298  and the global IDs. ---*/
21299 
21300  send_req = new SU2_MPI::Request[2*nSends];
21301  recv_req = new SU2_MPI::Request[2*nRecvs];
21302 
21303  unsigned long iMessage = 0;
21304  for (int ii=0; ii<size; ii++) {
21305  if ((ii != rank) && (nPoint_Recv[ii+1] > nPoint_Recv[ii])) {
21306  int ll = VARS_PER_POINT*nPoint_Recv[ii];
21307  int kk = nPoint_Recv[ii+1] - nPoint_Recv[ii];
21308  int count = VARS_PER_POINT*kk;
21309  int source = ii;
21310  int tag = ii + 1;
21311  SU2_MPI::Irecv(&(connRecv[ll]), count, MPI_DOUBLE, source, tag,
21312  MPI_COMM_WORLD, &(recv_req[iMessage]));
21313  iMessage++;
21314  }
21315  }
21316 
21317  /*--- Launch the non-blocking sends of the connectivity. ---*/
21318 
21319  iMessage = 0;
21320  for (int ii=0; ii<size; ii++) {
21321  if ((ii != rank) && (nPoint_Send[ii+1] > nPoint_Send[ii])) {
21322  int ll = VARS_PER_POINT*nPoint_Send[ii];
21323  int kk = nPoint_Send[ii+1] - nPoint_Send[ii];
21324  int count = VARS_PER_POINT*kk;
21325  int dest = ii;
21326  int tag = rank + 1;
21327  SU2_MPI::Isend(&(connSend[ll]), count, MPI_DOUBLE, dest, tag,
21328  MPI_COMM_WORLD, &(send_req[iMessage]));
21329  iMessage++;
21330  }
21331  }
21332 
21333  /*--- Repeat the process to communicate the global IDs. ---*/
21334 
21335  iMessage = 0;
21336  for (int ii=0; ii<size; ii++) {
21337  if ((ii != rank) && (nPoint_Recv[ii+1] > nPoint_Recv[ii])) {
21338  int ll = nPoint_Recv[ii];
21339  int kk = nPoint_Recv[ii+1] - nPoint_Recv[ii];
21340  int count = kk;
21341  int source = ii;
21342  int tag = ii + 1;
21343  SU2_MPI::Irecv(&(idRecv[ll]), count, MPI_UNSIGNED_LONG, source, tag,
21344  MPI_COMM_WORLD, &(recv_req[iMessage+nRecvs]));
21345  iMessage++;
21346  }
21347  }
21348 
21349  /*--- Launch the non-blocking sends of the global IDs. ---*/
21350 
21351  iMessage = 0;
21352  for (int ii=0; ii<size; ii++) {
21353  if ((ii != rank) && (nPoint_Send[ii+1] > nPoint_Send[ii])) {
21354  int ll = nPoint_Send[ii];
21355  int kk = nPoint_Send[ii+1] - nPoint_Send[ii];
21356  int count = kk;
21357  int dest = ii;
21358  int tag = rank + 1;
21359  SU2_MPI::Isend(&(idSend[ll]), count, MPI_UNSIGNED_LONG, dest, tag,
21360  MPI_COMM_WORLD, &(send_req[iMessage+nSends]));
21361  iMessage++;
21362  }
21363  }
21364 #endif
21365 
21366  /*--- Copy my own rank's data into the recv buffer directly. ---*/
21367 
21368  int mm = VARS_PER_POINT*nPoint_Recv[rank];
21369  int ll = VARS_PER_POINT*nPoint_Send[rank];
21370  int kk = VARS_PER_POINT*nPoint_Send[rank+1];
21371 
21372  for (int nn=ll; nn<kk; nn++, mm++) connRecv[mm] = connSend[nn];
21373 
21374  mm = nPoint_Recv[rank];
21375  ll = nPoint_Send[rank];
21376  kk = nPoint_Send[rank+1];
21377 
21378  for (int nn=ll; nn<kk; nn++, mm++) idRecv[mm] = idSend[nn];
21379 
21380  /*--- Wait for the non-blocking sends and recvs to complete. ---*/
21381 
21382 #ifdef HAVE_MPI
21383  int number = 2*nSends;
21384  for (int ii = 0; ii < number; ii++)
21385  SU2_MPI::Waitany(number, send_req, &ind, &status);
21386 
21387  number = 2*nRecvs;
21388  for (int ii = 0; ii < number; ii++)
21389  SU2_MPI::Waitany(number, recv_req, &ind, &status);
21390 
21391  delete [] send_req;
21392  delete [] recv_req;
21393 #endif
21394 
21395  /*--- Store the connectivity for this rank in the proper data
21396  structure before post-processing below. First, allocate the
21397  appropriate amount of memory for this section. ---*/
21398 
21399  Parallel_Data = new su2double*[VARS_PER_POINT];
21400  for (int jj = 0; jj < VARS_PER_POINT; jj++) {
21401  Parallel_Data[jj] = new su2double[nPoint_Recv[size]];
21402  for (int ii = 0; ii < nPoint_Recv[size]; ii++) {
21403  Parallel_Data[jj][idRecv[ii]] = connRecv[ii*VARS_PER_POINT+jj];
21404  }
21405  }
21406 
21407  /*--- Store the total number of local points my rank has for
21408  the current section after completing the communications. ---*/
21409 
21410  nParallel_Poin = nPoint_Recv[size];
21411 
21412  /*--- Reduce the total number of points we will write in the output files. ---*/
21413 
21414 #ifndef HAVE_MPI
21415  nGlobal_Poin_Par = nParallel_Poin;
21416 #else
21417  SU2_MPI::Allreduce(&nParallel_Poin, &nGlobal_Poin_Par, 1,
21419 #endif
21420 
21421  /*--- Free temporary memory from communications ---*/
21422 
21423  delete [] connSend;
21424  delete [] connRecv;
21425  delete [] idSend;
21426  delete [] idRecv;
21427  delete [] nPoint_Recv;
21428  delete [] nPoint_Send;
21429  delete [] nPoint_Flag;
21430 
21431  for (iPoint = 0; iPoint < nLocalPoint_Sort; iPoint++)
21432  delete [] Local_Data[iPoint];
21433  delete [] Local_Data;
21434 
21435 }
21436 
21438 
21439 }
#define B(i, j)
static void Error(std::string ErrorMsg, std::string FunctionName)
static void Barrier(Comm comm)
static int GetSize()
static void Gather(void *sendbuf, int sendcnt, Datatype sendtype, void *recvbuf, int recvcnt, Datatype recvtype, int root, Comm comm)
static void Isend(void *buf, int count, Datatype datatype, int dest, int tag, Comm comm, Request *request)
static void Allgather(void *sendbuf, int sendcnt, Datatype sendtype, void *recvbuf, int recvcnt, Datatype recvtype, Comm comm)
static void Allreduce(void *sendbuf, void *recvbuf, int count, Datatype datatype, Op op, Comm comm)
static int GetRank()
static void Alltoall(void *sendbuf, int sendcount, Datatype sendtype, void *recvbuf, int recvcount, Datatype recvtype, Comm comm)
static void Comm_size(Comm comm, int *size)
static void Waitany(int nrequests, Request *request, int *index, Status *status)
static void Irecv(void *buf, int count, Datatype datatype, int source, int tag, Comm comm, Request *request)
static void Bcast(void *buf, int count, Datatype datatype, int root, Comm comm)
Main class for defining a baseline solution from a restart file (for output).
Class to store a boundary for the FEM solver.
vector< CSurfaceElementFEM > surfElem
Vector of the local surface elements.
Main class for defining the problem; basically this class reads the configuration file,...
su2double GetTemperature_FreeStreamND(void)
Get the value of the non-dimensionalized freestream temperature.
su2double * GetDistortionRack(void)
Get the the coordinates where of the box where a subsonic region is imposed.
unsigned short GetKind_Solver(void)
Governing equations of the flow (it can be different from the run time equation).
void SetCFL(unsigned short val_mesh, su2double val_cfl)
Get the Courant Friedrich Levi number for each grid.
string GetRestart_AdjFEMFileName(void)
Get the name of the restart file for the structural adjoint variables.
su2double * GetRefOriginMoment(unsigned short val_marker)
Get reference origin for moment computation.
unsigned short GetiInst(void)
Get the current instance.
su2double * GetVelocity_FreeStreamND(void)
Get the vector of the non-dimensionalized freestream velocity.
su2double GetSurface_MassFlow(unsigned short val_imarker)
Get the massflow at an outlet boundary.
su2double GetNuFactor_FreeStream(void)
Get the value of the non-dimensionalized freestream turbulence intensity.
void SetSurface_IDC_Mach(unsigned short val_imarker, su2double val_surface_distortion)
Get the back pressure (static) at an outlet boundary.
unsigned short GetDirectDiff()
Get the direct differentation method.
unsigned short GetnMarker_Analyze(void)
Get the total number of moving markers.
bool GetWrt_Crd_Sol(void)
Get information about writing a binary coordinates file.
void SetSurface_PressureDrop(unsigned short val_imarker, su2double val_surface_pressuredrop)
Set the pressure drop between two surfaces.
su2double GetEnergy_Ref(void)
Get the value of the reference pressure for non-dimensionalization.
su2double GetPressureOut_BC()
Get the outlet pressure imposed as BC for internal flow.
void SetSurface_Enthalpy(unsigned short val_imarker, su2double val_surface_enthalpy)
Set the enthalpy at the surface.
unsigned long GetFSIIter(void)
Get the current FSI iteration number.
su2double * GetInlet_FlowDir(string val_index)
Get the flow direction unit vector at an inlet boundary.
bool GetExtraOutput(void)
Creates a tecplot file to visualize the partition made by the DDC software.
su2double GetEA_IntLimit(unsigned short index)
Get the integration limits for the equivalent area computation.
su2double GetSurface_DC60(unsigned short val_imarker)
Get the back pressure (static) at an outlet boundary.
su2double GetdCD_dCL(void)
Value of the weight of the CD, CL, CM optimization.
su2double GetInitial_BCThrust(void)
Get the value of the non-dimensionalized actuator disk turbulence intensity.
su2double GetdCMy_dCL(void)
Value of the weight of the CD, CL, CM optimization.
void SetSurface_Density(unsigned short val_imarker, su2double val_surface_density)
Set the density at the surface.
string GetMultizone_HistoryFileName(string val_filename, int val_iZone)
Append the zone index to the restart or the solution files.
bool GetContinuous_Adjoint(void)
Determines if problem is adjoint.
string GetMultiInstance_HistoryFileName(string val_filename, int val_iInst)
Append the instance index to the restart or the solution files.
bool GetInvDesign_HeatFlux(void)
Information about computing and plotting the equivalent area distribution.
unsigned short GetKind_ObjFunc(void)
Get the kind of objective function. There are several options: Drag coefficient, Lift coefficient,...
unsigned short GetKind_HybridRANSLES(void)
Get the Kind of Hybrid RANS/LES.
bool GetWrt_Residuals(void)
Get information about writing residuals to volume solution file.
unsigned short GetnTimeInstances(void)
Retrieves the number of periodic time instances for Harmonic Balance.
bool GetViscous(void)
Determines if problem is viscous.
su2double GetInlet_Ptotal(string val_index)
Get the total pressure at an inlet boundary.
unsigned short GetnMarker_All(void)
Get the total number of boundary markers.
su2double GetInc_Velocity_Ref(void)
Get the value of the reference velocity for custom incompressible non-dimensionalization.
unsigned long GetExtIter_OffSet(void)
Get the current internal iteration number.
unsigned long GetIter_dCL_dAlpha(void)
Number of iterations to evaluate dCL_dAlpha.
su2double GetSurface_IDR(unsigned short val_imarker)
Get the back pressure (static) at an outlet boundary.
unsigned short GetKind_Trans_Model(void)
Get the kind of the transition model.
su2double GetSurface_Temperature(unsigned short val_imarker)
Get the temperature at an outlet boundary.
su2double GetPressure_Ref(void)
Get the value of the reference pressure for non-dimensionalization.
unsigned short GetRef_Inc_NonDim(void)
Get the kind of incompressible non-dimensionalization.
bool GetWrt_Halo(void)
Get information about writing rind layers to the solution files.
su2double GetAoS_Offset(void)
Get the off set sideslip angle of the body. The solution and the geometry file are able to modifity t...
unsigned short GetKind_Turb_Model(void)
Get the kind of the turbulence model.
su2double GetAoS(void)
Get the angle of sideslip of the body. It relates to the rotation of the aircraft centerline from the...
su2double GetReynolds(void)
Get the Reynolds number. Dimensionless number that gives a measure of the ratio of inertial forces to...
unsigned short GetUnsteady_Simulation(void)
Provides information about the time integration, and change the write in the output files information...
unsigned short GetKind_SU2(void)
Get the kind of SU2 software component.
bool GetInvDesign_Cp(void)
Information about computing and plotting the equivalent area distribution.
long GetExtraHeatOutputZone(void)
Heat solver zone with extra screen output.
su2double GetSurface_Mach(unsigned short val_imarker)
Get the mach number at an outlet boundary.
unsigned short GetnMarker_ActDiskInlet(void)
Get the total number of boundary markers.
su2double GetSurface_IDC_Mach(unsigned short val_imarker)
Get the back pressure (static) at an outlet boundary.
void SetWrt_InletFile(bool val_wrt_inletfile)
Set information about writing a template inlet profile file.
bool GetVisualize_Surface_Def(void)
Creates a teot file to visualize the surface deformation deformation made by the DEF software.
bool GetIncrementalLoad(void)
Check if we want to apply an incremental load to the nonlinear structural simulation.
su2double GetSurface_SecondaryStrength(unsigned short val_imarker)
Get the secondary flow strength at the surface.
unsigned short GetnMarker_Transpiration(void)
Get the total number of transpiration markers.
bool GetWrt_Dynamic(void)
Get information about writing dynamic structural analysis headers and file extensions.
su2double GetdCMx_dCL(void)
Value of the weight of the CD, CL, CM optimization.
unsigned short GetMarker_All_KindBC(unsigned short val_marker)
Get the kind of boundary for each marker.
void SetSurface_Uniformity(unsigned short val_imarker, su2double val_surface_streamwiseuniformity)
Set the streamwise flow uniformity at the surface.
vector< string > fields
Tags for the different fields in a restart file.
su2double GetPressure_FreeStreamND(void)
Get the value of the non-dimensionalized freestream pressure.
su2double GetCFL(unsigned short val_mesh)
Get the Courant Friedrich Levi number for each grid.
bool GetRotating_Frame(void)
Get information about the rotational frame.
string GetMarker_Monitoring_TagBound(unsigned short val_marker)
Get the name of the surface defined in the geometry file.
bool GetBoolTurbomachinery(void)
Verify if there is Turbomachinery performance option specified from config file.
bool GetAeroelastic_Simulation(void)
Get information about the aeroelastic simulation.
unsigned short GetKind_SGS_Model(void)
Get the kind of the subgrid scale model.
void SetSurface_NormalVelocity(unsigned short val_imarker, su2double val_surface_normalvelocity)
Set the normal velocity at the surface.
su2double GetGamma(void)
Get the value of the Gamma of fluid (ratio of specific heats).
unsigned short GetnSpanMaxAllZones(void)
number span-wise sections to compute performance for turbomachinery.
su2double GetAoA(void)
Get the angle of attack of the body. This is the angle between a reference line on a lifting body (of...
su2double GetMach(void)
Get the value of the Mach number (velocity divided by speed of sound).
unsigned short GetnMarker_Monitoring(void)
Get the total number of monitoring markers.
bool GetWrt_SharpEdges(void)
Get information about writing residuals to volume solution file.
su2double GetdCMz_dCL(void)
Value of the weight of the CD, CL, CM optimization.
unsigned short GetKind_ConvNumScheme(void)
Get the kind of convective numerical scheme.
su2double GetRefLength(void)
Get the reference length for computing moment (the default value is 1).
bool GetGrid_Movement(void)
Get information about the grid movement.
su2double GetInlet_Ttotal(string val_index)
Get the total temperature at an inlet boundary.
su2double GetSemiSpan(void)
Get the wing semi span.
bool GetWrt_Csv_Sol(void)
Get information about writing a surface comma-separated values (CSV) solution file.
unsigned short GetKind_Regime(void)
Governing equations of the flow (it can be different from the run time equation).
su2double GetAoA_Offset(void)
Get the off set angle of attack of the body. The solution and the geometry file are able to modifity ...
bool GetGravityForce(void)
Get information about the gravity force.
unsigned short GetKind_DensityModel(void)
Option to define the density model for incompressible flows.
void SetSurface_MomentumDistortion(unsigned short val_imarker, su2double val_surface_momentumdistortion)
Set the momentum distortion at the surface.
su2double GetFlowAngleIn_BC()
Get the inlet flow angle imposed as BC for internal flow.
su2double GetGas_ConstantND(void)
Get the value of specific gas constant.
void SetiInst(unsigned short val_iInst)
Set the current instance.
unsigned short GetnMarker_ActDiskOutlet(void)
Get the total number of boundary markers.
string GetSurfAdjCoeff_FileName(void)
Get the name of the file with the surface information for the adjoint problem.
void SetSurface_TotalPressure(unsigned short val_imarker, su2double val_surface_totalpressure)
Set the total pressure at the surface.
su2double GetEA_ScaleFactor(void)
Get the integration limits for the equivalent area computation.
su2double GetSurface_Pressure(unsigned short val_imarker)
Get the pressure at an outlet boundary.
unsigned short GetnMarker_EngineInflow(void)
Get the total number of boundary markers.
short GetMarker_All_SendRecv(unsigned short val_marker)
Get the send-receive information for a marker val_marker.
su2double GetSurface_IDC(unsigned short val_imarker)
Get the back pressure (static) at an outlet boundary.
bool GetEngine_HalfModel(void)
Only halg of the engine is in the compputational grid.
void SetSurface_SecondOverUniform(unsigned short val_imarker, su2double val_surface_secondaryoverstream)
Set the relative secondary flow strength at the surface.
bool GetWrt_Vol_Sol(void)
Get information about writing a volume solution file.
su2double GetSurface_TotalTemperature(unsigned short val_imarker)
Get the total temperature at an outlet boundary.
void SetSurface_Temperature(unsigned short val_imarker, su2double val_surface_temperature)
Set the temperature at the surface.
void SetSurface_TotalTemperature(unsigned short val_imarker, su2double val_surface_totaltemperature)
Set the total temperature at the surface.
void SetSurface_SecondaryStrength(unsigned short val_imarker, su2double val_surface_secondarystrength)
Set the secondary flow strength at the surface.
unsigned short GetMarker_All_Plotting(unsigned short val_marker)
Get the plotting information for a marker val_marker.
su2double GetMach_Motion(void)
Get the mach number based on the mesh velocity and freestream quantities.
unsigned short GetMarker_All_Analyze(unsigned short val_marker)
Get the plotting information for a marker val_marker.
unsigned short GetnLocationStations(void)
Get the number of sections.
su2double GetDensity_Ref(void)
Get the value of the reference density for non-dimensionalization.
su2double GetSurface_Density(unsigned short val_imarker)
Get the density at an outlet boundary.
su2double GetFixAzimuthalLine(void)
Value of the azimuthal line to fix due to a misalignments of the nearfield.
su2double GetTemperature_Ref(void)
Get the value of the reference temperature for non-dimensionalization.
unsigned short GetnMarker_Turbomachinery(void)
number Turbomachinery performance option specified from config file.
su2double GetVelocity_Ref(void)
Get the value of the reference velocity for non-dimensionalization.
string GetMarker_TurboPerf_BoundIn(unsigned short index)
get inlet bounds name for Turbomachinery performance calculation.
string GetUnsteady_FileName(string val_filename, int val_iter)
Augment the input filename with the iteration number for an unsteady file.
unsigned short GetKind_Average(void)
Get the kind of marker analyze marker (area-averaged, mass flux averaged, etc).
su2double GetSurface_SecondOverUniform(unsigned short val_imarker)
Get the relative secondary flow strength at the surface.
string GetMesh_Out_FileName(void)
Get name of the output grid, this parameter is important for grid adaptation and deformation.
string GetMarker_All_TagBound(unsigned short val_marker)
Get the index of the surface defined in the geometry file.
bool GetFSI_Simulation(void)
Check if the simulation we are running is a FSI simulation.
string GetMarker_Analyze_TagBound(unsigned short val_marker)
Get the name of the surface defined in the geometry file.
static unsigned short GetnZone(string val_mesh_filename, unsigned short val_format, CConfig *config)
Gets the number of zones in the mesh file.
void SetRestart_Bandwidth_Agg(su2double val_restart_bandwidth_sum)
Set the sum of the bandwidth for writing binary restarts (to be averaged later).
string GetRestart_AdjFileName(void)
Get the name of the restart file for the adjoint variables (drag objective function).
unsigned short GetnMarker_TurboPerformance(void)
number Turbomachinery performance option specified from config file.
string GetConv_FileName(void)
Get the name of the file with the convergence history of the problem.
su2double GetSurface_TotalPressure(unsigned short val_imarker)
Get the total pressure at an outlet boundary.
su2double GetNacelleLocation(unsigned short val_index)
Get the defintion of the nacelle location.
void SetSurface_DC60(unsigned short val_imarker, su2double val_surface_distortion)
Get the back pressure (static) at an outlet boundary.
su2double GetPressure_ThermodynamicND(void)
Get the value of the non-dimensionalized thermodynamic pressure.
unsigned short GetnSpan_iZones(unsigned short iZone)
set number span-wise sections to compute 3D BC and performance for turbomachinery.
unsigned short GetGeo_Description(void)
Get Description of the geometry to be analyzed.
unsigned long GetExtIter(void)
Get the current external iteration number.
void SetSurface_Pressure(unsigned short val_imarker, su2double val_surface_pressure)
Set the pressure at the surface.
su2double GetSurface_NormalVelocity(unsigned short val_imarker)
Get the normal velocity at an outlet boundary.
bool GetWrt_Unsteady(void)
Get information about writing unsteady headers and file extensions.
unsigned short GetRef_NonDim(void)
Get the kind of non-dimensionalization.
long GetUnst_RestartIter(void)
Get the restart iteration number for unsteady simulations.
su2double GetTurb2LamViscRatio_FreeStream(void)
Get the value of the turbulent to laminar viscosity ratio.
unsigned short GetnObj(void)
Get the total number of objectives in kind_objective list.
unsigned short GetnMarker_EngineExhaust(void)
Get the total number of boundary markers.
unsigned long GetIntIter(void)
Get the current internal iteration number.
bool GetEnergy_Equation(void)
Flag for whether to solve the energy equation for incompressible flows.
bool GetVisualize_Volume_Def(void)
Creates a tecplot file to visualize the volume deformation deformation made by the DEF software.
bool GetFixed_CL_Mode(void)
Get information about whether to use fixed CL mode.
bool GetDiscrete_Adjoint(void)
Get the indicator whether we are solving an discrete adjoint problem.
unsigned short GetGeometricConditions(void)
Geometric conditions for the structural solver.
unsigned short GetDynamic_Analysis(void)
Provides information about the time integration of the structural analysis, and change the write in t...
unsigned short GetOutput_FileFormat(void)
Get the format of the output solution.
su2double GetCFL_AdaptParam(unsigned short val_index)
Get the values of the CFL adapation.
su2double GetStations_Bounds(unsigned short val_var)
Get the value of the limits for the sections.
string GetRestart_FEMFileName(void)
Get the name of the restart file for the structural variables.
unsigned short GetKind_RoeLowDiss(void)
Get the Kind of Roe Low Dissipation Scheme for Unsteady flows.
bool GetAxisymmetric(void)
Get information about the axisymmetric frame.
su2double GetInc_Density_Ref(void)
Get the value of the reference density for custom incompressible non-dimensionalization.
bool GetWrt_Limiters(void)
Get information about writing residuals to volume solution file.
su2double GetTurbulenceIntensity_FreeStream(void)
Get the value of the non-dimensionalized freestream turbulence intensity.
string GetRestart_FlowFileName(void)
Get the name of the restart file for the flow variables.
su2double GetSurface_MomentumDistortion(unsigned short val_imarker)
Get the momentum distortion at the surface.
string GetConv_FileName_FSI(void)
Get the name of the file with the convergence history of the problem for FSI applications.
string GetMarker_TurboPerf_BoundOut(unsigned short index)
get outlet bounds name for Turbomachinery performance calculation.
void SetSurface_Mach(unsigned short val_imarker, su2double val_surface_mach)
Set the mach number at the surface.
string GetSurfFlowCoeff_FileName(void)
Get the name of the file with the surface information for the flow problem.
su2double GetBulk_Modulus(void)
Get the value of the bulk modulus.
su2double GetRefArea(void)
Get the reference area for non dimensional coefficient computation. If the value from the is 0 then,...
string GetBreakdown_FileName(void)
Get the name of the file with the forces breakdown of the problem.
void SetSurface_IDR(unsigned short val_imarker, su2double val_surface_distortion)
Get the back pressure (static) at an outlet boundary.
string GetMultiInstance_FileName(string val_filename, int val_iInst)
Append the instance index to the restart or the solution files.
string GetObjFunc_Extension(string val_filename)
Append the input filename string with the appropriate objective function extension.
void SetSurface_IDC(unsigned short val_imarker, su2double val_surface_distortion)
Get the back pressure (static) at an outlet boundary.
void SetSurface_MassFlow(unsigned short val_imarker, su2double val_surface_massflow)
Set the massflow at the surface.
bool GetWeakly_Coupled_Heat(void)
Get the heat equation.
bool GetFrozen_Visc_Disc(void)
Provides information about the way in which the turbulence will be treated by the disc....
su2double GetLocationStations(unsigned short val_section)
Get the airfoil sections in the slicing process.
bool GetRestart(void)
Provides the restart information.
su2double GetRestart_Bandwidth_Agg(void)
Set the sum of the bandwidth for writing binary restarts (to be averaged later).
unsigned short GetnMGLevels(void)
Get the number of multigrid levels.
bool GetFrozen_Visc_Cont(void)
Provides information about the way in which the turbulence will be treated by the cont....
bool GetWrt_Performance(void)
Get information about writing the performance summary at the end of a calculation.
string GetMultizone_FileName(string val_filename, int val_iZone)
Append the zone index to the restart or the solution files.
bool GetBuffet_Monitoring(void)
Provides the buffet monitoring information.
bool GetWrt_Srf_Sol(void)
Get information about writing a surface solution file.
unsigned short GetFinestMesh(void)
Get the index of the finest grid.
bool GetWrt_Surface(void)
Write solution at each surface.
bool GetLow_MemoryOutput(void)
Get information about writing a volume solution file.
unsigned short GetSystemMeasurements(void)
Governing equations of the flow (it can be different from the run time equation).
bool GetEquivArea(void)
Information about computing and plotting the equivalent area distribution.
su2double GetSurface_Uniformity(unsigned short val_imarker)
Get the streamwise flow uniformity at the surface.
Class to define a FEM standard boundary face.
unsigned short GetNSubFaces(void) const
Function, which makes available the number of linear subfaces used for plotting, among others.
unsigned short GetNDOFsPerSubFace(void) const
Function, which makes available the number of DOFs of a linear subface, used for plotting,...
const unsigned short * GetSubFaceConn(void) const
Function, which makes available the the connectivity of the linear subfaces as a const pointer.
unsigned short GetVTK_Type(void) const
Function, which makes available the type of the element.
Class to define a FEM standard element.
const unsigned short * GetSubConnType2(void) const
Function, which makes available the the connectivity of the linear elements of type 2 as a const poin...
unsigned short GetNSubElemsType1(void) const
Function, which makes available the number of sub-elements of type 1 for plotting.
const unsigned short * GetSubConnType1(void) const
Function, which makes available the the connectivity of the linear elements of type 1 as a const poin...
unsigned short GetVTK_Type2(void) const
Function, which makes available the type of the element in subConn2ForPlotting.
unsigned short GetNDOFsPerSubElem(unsigned short val_VTK_Type) const
Function, which makes available the number of DOFs of a linear element, used for plotting.
unsigned short GetNSubElemsType2(void) const
Function, which makes available the number of sub-elements of type 2 for plotting.
unsigned short GetVTK_Type1(void) const
Function, which makes available the type of the element in subConn1ForPlotting.
Main class for defining the Thermo-Physical Model a child class for each particular Model (Ideal-Gas,...
Definition: fluid_model.hpp:64
su2double GetCp()
Get fluid specific heat at constant pressure.
Definition: fluid_model.inl:47
su2double GetPressure()
Get fluid pressure.
Definition: fluid_model.inl:40
su2double GetSoundSpeed()
Get fluid speed of sound.
Definition: fluid_model.inl:41
virtual void SetTDState_rhoe(su2double rho, su2double e)
virtual member that would be different for each gas model implemented
Definition: fluid_model.inl:93
su2double GetLaminarViscosity()
Get fluid dynamic viscosity.
Definition: fluid_model.inl:58
su2double GetTemperature()
Get fluid temperature.
Definition: fluid_model.inl:46
Parent class for defining the geometry of the problem (complete geometry, multigrid agglomerated geom...
void ComputeAirfoil_Section(su2double *Plane_P0, su2double *Plane_Normal, su2double MinXCoord, su2double MaxXCoord, su2double MinYCoord, su2double MaxYCoord, su2double MinZCoord, su2double MaxZCoord, su2double *FlowVariable, vector< su2double > &Xcoord_Airfoil, vector< su2double > &Ycoord_Airfoil, vector< su2double > &Zcoord_Airfoil, vector< su2double > &Variable_Airfoil, bool original_surface, CConfig *config)
A virtual member.
virtual unsigned long GetGlobal_nPointDomain()
A virtual member.
virtual unsigned long GetnElemPris()
A virtual member.
unsigned short GetnDim(void)
Get number of coordinates.
CPrimalGrid *** bound
Boundary vector (primal grid information).
unsigned long GetnElem(void)
Get number of elements.
unsigned long GetnElem_Bound(unsigned short val_marker)
Get the number of boundary elements.
unsigned long GetnPointDomain(void)
Get number of real points (that belong to the domain).
unsigned long GetnVertex(unsigned short val_marker)
Get number of vertices.
CVertex *** vertex
Boundary Vertex vector (dual grid information).
virtual unsigned long GetnElemHexa()
A virtual member.
virtual su2double GetSensitivity(unsigned long iPoint, unsigned short iDim)
A virtual member.
virtual unsigned long GetnElemTria()
A virtual member.
su2double * GetSpanWiseValue(unsigned short val_marker)
Get number of vertices.
unsigned short GetnZone(void)
Get number of zones.
unsigned long GetnPoint(void)
Get number of points.
virtual unsigned long GetnElemQuad()
A virtual member.
virtual unsigned long GetnElemPyra()
A virtual member.
CPrimalGrid ** elem
Element vector (primal grid information).
virtual unsigned long GetnElemTetr()
A virtual member.
CPoint ** node
Node vector (dual grid information).
unsigned long * nVertex
Number of vertex for each marker.
Main class for doing the space integration, time integration, and monitoring of a system of Partial D...
Class which contains all the variables for the DG FEM solver.
CFEMStandardElement * GetStandardElementsSol(void)
Function, which makes available the standard volume elements of the solution.
unsigned long GetNVolElemOwned(void)
Function, which makes available the number of owned volume elements in the local FEM mesh.
CVolumeElementFEM * GetVolElem(void)
Function, which makes available the volume elements in the local FEM mesh.
CBoundaryFEM * GetBoundaries(void)
Function, which makes available the boundaries of the local FEM mesh.
CFEMStandardBoundaryFace * GetStandardBoundaryFacesSol(void)
Function, which makes available the standard boundary faces of the solution.
void MergeVolumetricConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type)
Merge the connectivity for a single element type from all processors for the FEM solver.
void SortOutputData_FEM(CConfig *config, CGeometry *geometry)
Sort the output data for each grid node into a linear partitioning across all processors (DG-FEM solv...
void SetParaview_ASCII(CConfig *config, CGeometry *geometry, unsigned short val_iZone, unsigned short val_nZone, bool surf_sol)
Write a Paraview ASCII solution file.
void WriteTecplotASCII_Parallel(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone, unsigned short val_nZone, unsigned short val_iInst, unsigned short val_nInst, bool surf_sol)
Write the solution data and connectivity to a Tecplot ASCII mesh file in parallel.
void SetTecplotBinary_SurfaceSolution(CConfig *config, CGeometry *geometry, unsigned short val_iZone)
Write solution data to a Tecplot binary surface solution file.
void DeallocateInletCoordinates(CConfig *config, CGeometry *geometry)
Deallocate temporary memory needed for merging and writing inlet boundary coordinates.
void LoadLocalData_Base(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Load the desired solution data into a structure used for parallel reordering and output file writing ...
void SortVolumetricConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type)
Sort the connectivity for a single volume element type into a linear partitioning across all processo...
void SetTecplotASCII(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone, unsigned short val_nZone, bool surf_sol)
Write a Tecplot ASCII solution file.
void SortOutputData(CConfig *config, CGeometry *geometry)
Sort the output data for each grid node into a linear partitioning across all processors.
void SetMesh_Files(CGeometry **geometry, CConfig **config, unsigned short val_nZone, bool new_file, bool su2_file)
Writes and organizes the all the output files, except the history one, for serial computations.
void WriteParaViewBinary_Parallel(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone, unsigned short val_nZone, bool surf_sol)
Write a Paraview binary solution file with parallel output.
void SetSTL_MeshASCII(CConfig *config, CGeometry *geometry)
Write the nodal coordinates and connectivity to a stl ASCII mesh file.
void MergeCoordinates(CConfig *config, CGeometry *geometry)
Merge the node coordinates from all processors.
void SortSurfaceConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type)
Sort the connectivity for a single surface element type into a linear partitioning across all process...
void DeallocateSolution(CConfig *config, CGeometry *geometry)
Deallocate temporary memory needed for merging and writing solution variables.
void LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Load the desired solution data into a structure used for parallel reordering and output file writing ...
void SpecialOutput_Distortion(CSolver *solver, CGeometry *geometry, CConfig *config, bool output)
Create and write the file with the flow coefficient on the surface.
void SetResult_Files(CSolver *****solver_container, CGeometry ****geometry, CConfig **config, unsigned long iExtIter, unsigned short val_nZone)
Writes and organizes the all the output files, except the history one, for serial computations.
void SortSurfaceConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type)
Sort the connectivity for a single surface element type into a linear partitioning across all process...
void SetConvHistory_Body(ofstream *ConvHist_file, CGeometry ****geometry, CSolver *****solver_container, CConfig **config, CIntegration ****integration, bool DualTime, su2double timeused, unsigned short val_iZone, unsigned short val_iInst)
Write the history file and the convergence on the screen for serial computations.
void LoadLocalData_FEM(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Load the desired solution data into a structure used for parallel reordering and output file writing ...
void SortVolumetricConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type)
Sort the connectivity for a single volume element type into a linear partitioning across all processo...
void SetCSV_MeshASCII(CConfig *config, CGeometry *geometry)
Write the nodal coordinates and connectivity to a n3d ASCII mesh file.
void SetFieldViewBinary(CConfig *config, CGeometry *geometry, unsigned short val_iZone, unsigned short val_nZone)
Write solution data to a Tecplot binary volume solution file.
void MergeBaselineSolution(CConfig *config, CGeometry *geometry, CSolver *solver, unsigned short val_iZone)
Merge the solution into a data structure used for output file writing.
void MergeVolumetricConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type)
Merge the connectivity for a single element type from all processors.
void MergeSurfaceConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type)
Merge the connectivity for a single element type from all processors.
void SetParaview_MeshASCII(CConfig *config, CGeometry *geometry, unsigned short val_iZone, unsigned short val_nZone, bool surf_sol, bool new_file)
Write a Paraview ASCII solution file.
~COutput(void)
Destructor of the class.
void SetTecplotBinary_DomainSolution(CConfig *config, CGeometry *geometry, unsigned short val_iZone)
Write solution data to a Tecplot binary volume solution file.
void PrepareOffsets(CConfig *config, CGeometry *geometry)
Prepare the number of points and offsets for linear partitioning that are needed for output.
void MergeSurfaceConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type)
Merge the connectivity for a single element type from all processors for the FEM solver.
void DeallocateSurfaceData_Parallel(CConfig *config, CGeometry *geometry)
Deallocate temporary memory needed for merging and writing output data in parallel.
void SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, CConfig *config, bool output)
Writes forces at different sections.
void SetTecplotBinary_SurfaceMesh(CConfig *config, CGeometry *geometry, unsigned short val_iZone)
Write the coordinates and connectivity to a Tecplot binary surface mesh file.
void WriteRestart_Parallel_Binary(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone, unsigned short val_iInst)
Write a native SU2 restart file (binary) in parallel.
int size
MPI Size.
void SetResult_Files_FEM(CSolver ****solver_container, CGeometry ***geometry, CConfig **config, unsigned long iExtIter, unsigned short val_nZone)
Writes and organizes the all the output files, except the history one, for serial computations with t...
void SetRestart(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Write a native SU2 restart file.
void MergeSolution_FEM(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Merge the FEM solution into a data structure used for output file writing.
void MergeConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short val_iZone)
Merge the FEM geometry into a data structure used for output file writing.
void DeallocateConnectivity(CConfig *config, CGeometry *geometry, bool surf_sol)
Deallocate temporary memory needed for merging and writing connectivity.
void SetCFL_Number(CSolver *****solver_container, CConfig **config, unsigned short val_iZone)
Write the history file and the convergence on the screen for serial computations.
void SortOutputData_Surface_FEM(CConfig *config, CGeometry *geometry)
Sort the surface output data for each grid node into a linear partitioning across all processors (DG-...
void SetHeatFlux_InverseDesign(CSolver *solver_container, CGeometry *geometry, CConfig *config, unsigned long iExtIter)
Writes inverse design.
void SpecialOutput_Turbo(CSolver *****solver_container, CGeometry ****geometry, CConfig **config, unsigned short val_iZone, bool output)
Write the output file for spanwise turboperformance.
void WriteTurboPerfConvHistory(CConfig *config)
Compute .
void WriteParaViewASCII_Parallel(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone, unsigned short val_nZone, unsigned short val_iInst, unsigned short val_nInst, bool surf_sol)
Write a Paraview ASCII solution file with parallel output.
void MergeInletCoordinates(CConfig *config, CGeometry *geometry)
Merge the node coordinates of all inlet boundaries from all processors.
void SetTecplotBinary_DomainMesh(CConfig *config, CGeometry *geometry, unsigned short val_iZone)
Write the nodal coordinates and connectivity to a Tecplot binary mesh file.
int rank
MPI Rank.
void DeallocateCoordinates(CConfig *config, CGeometry *geometry)
Deallocate temporary memory needed for merging and writing coordinates.
void DeallocateData_Parallel(CConfig *config, CGeometry *geometry)
Deallocate temporary memory needed for merging and writing output data in parallel.
void MergeBaselineSolution_FEM(CConfig *config, CGeometry *geometry, CSolver *solver, unsigned short val_iZone)
Merge the solution into a data structure used for output file writing (DG-FEM).
void SetResult_Files_Parallel(CSolver *****solver_container, CGeometry ****geometry, CConfig **config, unsigned long iExtIter, unsigned short val_nZone, unsigned short *nInst)
Writes and organizes the all the output files, except the history one, for parallel computations.
void MergeConnectivity(CConfig *config, CGeometry *geometry, unsigned short val_iZone)
Merge the geometry into a data structure used for output file writing.
void LoadLocalData_Elasticity(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Load the desired solution data into a structure used for parallel reordering and output file writing ...
void SortConnectivity(CConfig *config, CGeometry *geometry, unsigned short val_iZone)
Sort the connectivities (volume and surface) into data structures used for output file writing.
void Write_InletFile_Flow(CConfig *config, CGeometry *geometry, CSolver **solver)
Write a template inlet profile file for all inlets for flow problems.
void SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry, CConfig *config, bool output)
Writes equivalent area.
void SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, CSolver *FlowSolver, unsigned long iExtIter, unsigned short val_iZone, unsigned short val_iInst)
Create and write the file with the flow coefficient on the surface.
void SetSensitivity_Files(CGeometry **geometry, CConfig **config, unsigned short val_nZone)
Write the sensitivity (including mesh sensitivity) computed with the discrete adjoint method on the s...
void SortConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short val_iZone)
Sort the connectivities (volume and surface) into data structures used for output file writing (DG-FE...
void SetConvHistory_Header(ofstream *ConvHist_file, CConfig *config, unsigned short val_iZone, unsigned short val_iInst)
Write the header of the history file.
void SetFieldViewASCII(CConfig *config, CGeometry *geometry, unsigned short val_iZone, unsigned short val_nZone)
Write a Tecplot ASCII solution file.
void SetTecplotASCII_Mesh(CConfig *config, CGeometry *geometry, unsigned short val_iZone, bool surf_sol, bool new_file)
Write the nodal coordinates and connectivity to a n3d ASCII mesh file.
void WriteCoordinates_Binary(CConfig *config, CGeometry *geometry, unsigned short val_iZone)
Write the nodal coordinates to a binary file.
Definition: output_su2.cpp:252
void WriteCSV_Slice(CConfig *config, CGeometry *geometry, CSolver *FlowSolver, unsigned long iExtIter, unsigned short val_iZone, unsigned short val_direction)
Create and write a CSV file with a slice of data.
COutput(CConfig *congig)
Constructor of the class.
void WriteRestart_Parallel_ASCII(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone, unsigned short val_iInst)
Write a native SU2 restart file (ASCII) in parallel.
void SortOutputData_Surface(CConfig *config, CGeometry *geometry)
Sort the surface output data for each grid node into a linear partitioning across all processors.
void SetBaselineResult_Files(CSolver ***solver, CGeometry ***geometry, CConfig **config, unsigned long iExtIter, unsigned short val_nZone)
Writes and organizes the all the output files, except the history one, for serial computations.
void SpecialOutput_HarmonicBalance(CSolver *****solver, CGeometry ****geometry, CConfig **config, unsigned short iZone, unsigned short val_nZone, bool output)
Write the output file for harmonic balance for each time-instance.
void SetCp_InverseDesign(CSolver *solver_container, CGeometry *geometry, CConfig *config, unsigned long iExtIter)
Writes inverse design.
void SetBaselineResult_Files_FEM(CSolver ***solver, CGeometry ***geometry, CConfig **config, unsigned long iExtIter, unsigned short val_nZone)
Writes and organizes the all the output files, except the history one, for DG-FEM simulations (SU2_SO...
void SpecialOutput_FSI(ofstream *FSIHist_file, CGeometry ****geometry, CSolver *****solver_container, CConfig **config, CIntegration ****integration, unsigned long iExtIter, unsigned short ZONE_FLOW, unsigned short ZONE_STRUCT, bool header)
Create and write the file with the FSI convergence history.
void LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Load the desired solution data into a structure used for parallel reordering and output file writing ...
void SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geometry, CConfig *config, bool output)
Writes one dimensional output.
void MergeSolution(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Merge the solution into a data structure used for output file writing.
void SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry ****geometry, CConfig **config, unsigned short val_iZone, bool output)
Write the history file and the convergence on the screen for serial computations.
void DeallocateConnectivity_Parallel(CConfig *config, CGeometry *geometry, bool surf_sol)
Deallocate temporary memory needed for merging and writing connectivity in parallel.
void LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone)
Load the desired solution data into a structure used for parallel reordering and output file writing ...
void SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, CSolver *AdjSolver, CSolver *FlowSolution, unsigned long iExtIter, unsigned short val_iZone, unsigned short val_iInst)
Create and write the file with the adjoint coefficients on the surface for serial computations.
void SetSU2_MeshASCII(CConfig *config, CGeometry *geometry, unsigned short val_iZone, ofstream &output_file)
Write the nodal coordinates and connectivity to a Tecplot binary mesh file.
Definition: output_su2.cpp:40
void MergeCoordinates_FEM(CConfig *config, CGeometry *geometry)
Merge the node coordinates from all processors for the FEM solver.
bool GetDomain(void)
For parallel computation, its indicates if a point must be computed or not.
su2double GetWall_Distance(void)
Get the value of the distance to the nearest wall.
su2double * GetGridVel(void)
Get the value of the grid velocity at the point.
su2double GetCoord(unsigned short val_dim)
Get the coordinates dor the control volume.
unsigned long GetGlobalIndex(void)
Get the global index in a parallel computation.
su2double GetSharpEdge_Distance(void)
Get the value of the distance to a sharp edge.
virtual unsigned long GetNode(unsigned short val_node)=0
A pure virtual member.
virtual unsigned short GetVTK_Type(void)=0
A pure virtual member.
Main class for defining the PDE solution, it requires a child class for each particular solver (Euler...
virtual su2double GetCPressureTarget(unsigned short val_marker, unsigned long val_vertex)
A virtual member.
unsigned short GetnOutputVariables(void)
Get the number of variables of the problem.
virtual su2double GetVelocity_Inf(unsigned short val_dim)
A virtual member.
virtual su2double GetTotal_Custom_ObjFunc(void)
A virtual member.
virtual void SetTotal_HeatFluxDiff(su2double val_heat)
A virtual member.
virtual su2double GetStrainMag_Max(void)
A virtual member.
virtual su2double GetTotal_Sens_Mach(void)
A virtual member.
virtual void SetTotal_IDC_Mach(su2double val_Total_IDC_Mach)
A virtual member.
virtual su2double GetSurface_CL(unsigned short val_marker)
A virtual member.
virtual su2double GetTotal_Sens_Temp(void)
Set the total farfield temperature sensitivity coefficient.
virtual su2double GetCSkinFriction(unsigned short val_marker, unsigned long val_vertex, unsigned short val_dim)
A virtual member.
virtual su2double GetTotal_CoPx(void)
A virtual member.
virtual su2double GetAllBound_CFz_Inv(void)
A virtual member.
virtual su2double GetYPlus(unsigned short val_marker, unsigned long val_vertex)
A virtual member.
virtual su2double GetTotal_AeroCD(void)
A virtual member.
virtual su2double GetSurface_CFz_Visc(unsigned short val_marker)
A virtual member.
virtual su2double GetRelaxCoeff()
A virtual member.
virtual su2double GetCPressure(unsigned short val_marker, unsigned long val_vertex)
A virtual member.
virtual su2double GetSurface_CL_Inv(unsigned short val_marker)
A virtual member.
virtual su2double GetTotal_AvgTemperature(void)
A virtual member.
su2double GetRes_RMS(unsigned short val_var)
Get the maximal residual, this is useful for the convergence history.
CSysVector LinSysRes
vector to store iterative residual of implicit linear system.
virtual su2double GetTotal_CMz(void)
A virtual member.
virtual su2double GetSurface_CFx_Visc(unsigned short val_marker)
A virtual member.
virtual su2double GetTotal_CMy(void)
A virtual member.
virtual su2double GetTotal_ComboObj(void)
Provide the total "combo" objective (weighted sum of other values).
unsigned long GetPoint_Max(unsigned short val_var)
Get the maximal residual, this is useful for the convergence history.
virtual su2double GetTotal_SolidCD(void)
A virtual member.
virtual su2double GetAllBound_CSF_Mnt(void)
A virtual member.
virtual su2double GetHeatFluxTarget(unsigned short val_marker, unsigned long val_vertex)
A virtual member.
virtual su2double GetSurface_CL_Mnt(unsigned short val_marker)
A virtual member.
virtual su2double GetSurface_CFy(unsigned short val_marker)
A virtual member.
virtual su2double GetAllBound_CEff_Visc(void)
A virtual member.
virtual su2double GetSurface_CD_Inv(unsigned short val_marker)
A virtual member.
virtual su2double GetTotal_CD(void)
A virtual member.
string * OutputHeadingNames
virtual su2double GetSurface_Buffet_Metric(unsigned short val_marker)
A virtual member.
virtual su2double GetAllBound_CFy_Inv(void)
A virtual member.
virtual su2double GetOmega_Inf(void)
A virtual member.
virtual su2double GetTotal_Buffet_Metric(void)
A virtual member.
virtual unsigned long GetnDOFsGlobal(void)
A virtual member.
virtual su2double GetNuTilde_Inf(void)
A virtual member.
virtual su2double GetAllBound_CFx_Visc(void)
A virtual member.
virtual su2double GetAllBound_CMx_Mnt(void)
A virtual member.
virtual su2double GetAllBound_CFz_Mnt(void)
A virtual member.
virtual su2double GetSurface_CMy_Visc(unsigned short val_marker)
A virtual member.
virtual su2double GetAllBound_CD_Inv(void)
A virtual member.
virtual su2double GetTotal_CT(void)
A virtual member.
virtual su2double GetAllBound_CMx_Visc(void)
A virtual member.
virtual su2double GetTotal_CNearFieldOF(void)
A virtual member.
virtual su2double GetAllBound_CFy_Mnt(void)
A virtual member.
virtual su2double GetSurface_CMz_Inv(unsigned short val_marker)
A virtual member.
virtual su2double GetHeatFlux(unsigned short val_marker, unsigned long val_vertex)
A virtual member.
virtual su2double GetTotal_CEquivArea(void)
A virtual member.
virtual su2double GetSurface_CFy_Inv(unsigned short val_marker)
A virtual member.
virtual su2double GetAllBound_CMz_Visc(void)
A virtual member.
virtual su2double GetAllBound_CL_Visc(void)
A virtual member.
virtual su2double GetTotal_CMerit(void)
A virtual member.
virtual void SetTotal_CEquivArea(su2double val_cequivarea)
A virtual member.
virtual su2double GetOmega_Max(void)
A virtual member.
virtual su2double GetTotal_CL(void)
A virtual member.
virtual su2double GetSurface_CFx_Mnt(unsigned short val_marker)
A virtual member.
virtual su2double GetAllBound_CD_Mnt(void)
A virtual member.
virtual su2double GetTotal_Sens_AoA(void)
A virtual member.
virtual su2double GetSurface_CMy_Inv(unsigned short val_marker)
A virtual member.
virtual su2double GetTotal_NetThrust(void)
A virtual member.
unsigned short GetnVar(void)
Get the number of variables of the problem.
su2double * GetPoint_Max_Coord(unsigned short val_var)
Get the location of the maximal residual, this is useful for the convergence history.
virtual su2double GetForceCoeff()
A virtual member.
virtual su2double GetTotal_CFx(void)
A virtual member.
virtual su2double GetTotal_CEff(void)
A virtual member.
virtual su2double GetAllBound_CMy_Inv(void)
A virtual member.
virtual su2double GetTotal_Sens_ModVel(void)
A virtual member.
virtual su2double GetTotal_IDC(void)
A virtual member.
virtual su2double GetAllBound_CFy_Visc(void)
A virtual member.
virtual su2double GetAllBound_CD_Visc(void)
A virtual member.
virtual void SetTotal_DC60(su2double val_Total_DC60)
A virtual member.
virtual su2double GetSurface_CMx_Visc(unsigned short val_marker)
A virtual member.
virtual su2double GetTotal_Sens_Geo(void)
A virtual member.
virtual su2double GetSurface_CFx_Inv(unsigned short val_marker)
A virtual member.
virtual su2double GetAllBound_CFx_Inv(void)
A virtual member.
virtual su2double GetSurface_CMy_Mnt(unsigned short val_marker)
A virtual member.
virtual su2double GetSurface_CMz(unsigned short val_marker)
A virtual member.
virtual su2double GetTotal_HeatFlux(void)
A virtual member.
virtual su2double GetSurface_CSF_Inv(unsigned short val_marker)
A virtual member.
virtual su2double GetTotal_OFRefGeom(void)
A virtual member.
virtual void Evaluate_ObjFunc(CConfig *config)
Compute weighted-sum "combo" objective output.
virtual su2double GetAllBound_CMy_Visc(void)
A virtual member.
virtual su2double GetTotal_CFy(void)
A virtual member.
su2double GetMin_Delta_Time(void)
Get the value of the minimum delta time.
CVariable ** node
Vector which the define the variables for each problem.
virtual su2double GetGlobal_Sens_Nu(unsigned short iVal)
A virtual member.
virtual su2double GetSurface_CSF_Mnt(unsigned short val_marker)
A virtual member.
virtual su2double GetDensity_Inf(void)
A virtual member.
virtual su2double GetTotal_CSF(void)
A virtual member.
virtual su2double GetSurface_CEff_Mnt(unsigned short val_marker)
A virtual member.
virtual su2double GetSurface_CEff_Visc(unsigned short val_marker)
A virtual member.
virtual su2double GetGlobal_Sens_E(unsigned short iVal)
A virtual member.
virtual su2double GetTotal_MaxHeatFlux(void)
A virtual member.
virtual su2double GetTotal_IDR(void)
A virtual member.
virtual su2double GetAllBound_CL_Inv(void)
A virtual member.
virtual CFluidModel * GetFluidModel(void)
Compute the pressure at the infinity.
virtual su2double GetSurface_CFz_Mnt(unsigned short val_marker)
A virtual member.
virtual void SetTotal_ComboObj(su2double ComboObj)
Set the total "combo" objective (weighted sum of other values).
virtual su2double GetTotal_CoPz(void)
A virtual member.
virtual su2double GetTotal_Sens_BPress(void)
Get the total back pressure sensitivity coefficient.
virtual void SetHeatFluxTarget(unsigned short val_marker, unsigned long val_vertex, su2double val_heat)
A virtual member.
virtual su2double GetAllBound_CMz_Mnt(void)
A virtual member.
virtual su2double GetLoad_Increment(void)
A virtual member.
virtual su2double GetTotal_Power(void)
A virtual member.
virtual su2double GetSurface_CMz_Visc(unsigned short val_marker)
A virtual member.
virtual su2double GetSurface_CMx(unsigned short val_marker)
A virtual member.
virtual su2double GetTotal_CMx(void)
A virtual member.
virtual su2double GetTotal_CFEA(void)
A virtual member.
virtual su2double GetAllBound_CFx_Mnt(void)
A virtual member.
virtual su2double GetAllBound_CSF_Visc(void)
A virtual member.
CSysVector OutputVariables
vector to store the extra variables to be written.
virtual su2double GetSurface_CSF(unsigned short val_marker)
A virtual member.
virtual su2double * GetVecSolDOFs(void)
A virtual member.
virtual su2double GetSurface_CFy_Visc(unsigned short val_marker)
A virtual member.
virtual void SetCPressureTarget(unsigned short val_marker, unsigned long val_vertex, su2double val_pressure)
A virtual member.
virtual su2double GetFSI_Residual()
A virtual member.
virtual su2double GetTotal_CoPy(void)
A virtual member.
virtual void SetTotal_IDR(su2double val_Total_IDR)
A virtual member.
su2double GetMax_Delta_Time(void)
Get the value of the maximum delta time.
virtual su2double GetRes_FEM(unsigned short val_var)
Get the residual for FEM structural analysis.
virtual su2double GetSurface_CD_Visc(unsigned short val_marker)
A virtual member.
virtual su2double GetAllBound_CEff_Inv(void)
A virtual member.
virtual su2double GetModVelocity_Inf(void)
A virtual member.
virtual su2double GetAllBound_CEff_Mnt(void)
A virtual member.
virtual su2double GetTotal_CFz(void)
A virtual member.
virtual su2double GetSurface_CFy_Mnt(unsigned short val_marker)
A virtual member.
virtual su2double GetAllBound_CMx_Inv(void)
A virtual member.
virtual su2double GetSurface_CMy(unsigned short val_marker)
A virtual member.
virtual su2double GetSurface_CEff_Inv(unsigned short val_marker)
A virtual member.
virtual su2double GetSurface_CFx(unsigned short val_marker)
A virtual member.
virtual su2double GetCSensitivity(unsigned short val_marker, unsigned long val_vertex)
A virtual member.
virtual su2double GetSurface_CFz_Inv(unsigned short val_marker)
A virtual member.
virtual su2double GetSurface_CSF_Visc(unsigned short val_marker)
A virtual member.
virtual su2double GetSurface_CL_Visc(unsigned short val_marker)
A virtual member.
virtual su2double GetTke_Inf(void)
A virtual member.
virtual su2double GetAllBound_CFz_Visc(void)
A virtual member.
virtual su2double GetTotal_Sens_Press(void)
Set the total farfield pressure sensitivity coefficient.
virtual su2double GetAllBound_CMy_Mnt(void)
A virtual member.
virtual su2double GetSurface_CMx_Inv(unsigned short val_marker)
A virtual member.
virtual su2double GetTotal_Cmu(void)
A virtual member.
virtual su2double GetSurface_CMx_Mnt(unsigned short val_marker)
A virtual member.
virtual su2double GetSurface_CD_Mnt(unsigned short val_marker)
A virtual member.
virtual void SetTotal_CpDiff(su2double val_pressure)
A virtual member.
virtual su2double GetAllBound_CMz_Inv(void)
A virtual member.
virtual void SetTotal_IDC(su2double val_Total_IDC)
A virtual member.
virtual su2double GetTotal_OFRefNode(void)
A virtual member.
virtual su2double GetSurface_CMz_Mnt(unsigned short val_marker)
A virtual member.
virtual su2double GetSurface_CFz(unsigned short val_marker)
A virtual member.
virtual su2double GetSurface_CD(unsigned short val_marker)
A virtual member.
virtual su2double GetTotal_CQ(void)
A virtual member.
virtual su2double GetAllBound_CSF_Inv(void)
A virtual member.
virtual su2double GetAllBound_CL_Mnt(void)
A virtual member.
virtual su2double GetSurface_CEff(unsigned short val_marker)
A virtual member.
virtual su2double GetPressure_Inf(void)
A virtual member.
su2double * GetBlock(unsigned long val_ipoint)
Get the value of the residual.
virtual su2double GetTemperature(void)
A virtual member.
virtual su2double GetVonMises_Stress(void)
A virtual member.
virtual su2double GetSolution_Vel(unsigned short val_var)
Get the velocity (Structural Analysis).
virtual su2double GetLimiter_Primitive(unsigned short val_var)
A virtual member.
su2double GetSensor(void)
Get the pressure sensor.
virtual su2double GetSoundSpeed(void)
A virtual member.
virtual su2double GetSensitivityTranspiration(void)
Get the transpiration velocity Sensitivity at the node.
void SetSolution(su2double *val_solution)
Set the value of the solution.
virtual su2double GetGammaBC(void)
A virtual member.
virtual su2double GetVelocity(unsigned short val_dim)
A virtual member.
virtual su2double GetDensity(void)
A virtual member.
virtual su2double GetEnthalpy(void)
A virtual member.
virtual su2double GetEddyViscosity(void)
A virtual member.
su2double GetSolution(unsigned short val_var)
Get the solution.
su2double * GetLimiter(void)
Get the value of the slope limiter.
virtual su2double GetVelocity2(void)
A virtual member.
virtual su2double GetDES_LengthScale(void)
A virtual member.
virtual su2double GetSpecificHeatCp(void)
A virtual member.
virtual su2double GetGeometry_CrossTerm_Derivative(unsigned short val_var)
A virtual member. Get the geometry solution.
virtual su2double GetRoe_Dissipation(void)
A virtual member.
virtual su2double GetPressure(void)
A virtual member.
virtual su2double GetSensitivity(unsigned short iDim)
Get the Sensitivity at the node.
virtual su2double GetSpecificHeatCv(void)
A virtual member.
virtual su2double * GetStress_FEM(void)
A virtual member.
virtual su2double GetLaminarViscosity(void)
A virtual member.
su2double GetSolution_Old(unsigned short val_var)
Get the old solution of the problem (Runge-Kutta method)
virtual su2double GetSolution_Accel(unsigned short val_var)
Get the acceleration (Structural Analysis).
void GetNormal(su2double *val_normal)
Copy the the normal vector of a face.
short GetRotation_Type(void)
Get the type of rotation associated to the vertex.
unsigned long GetNode(void)
Get the node of the vertex.
Class to store a volume element for the FEM solver.
unsigned long offsetDOFsSolLocal
Local offset of the solution DOFs of this element.
unsigned short indStandardElement
Index in the vector of standard elements.
vector< su2double > coorSolDOFs
The coordinates of the solution DOFs of this element.
unsigned long offsetDOFsSolGlobal
Global offset of the solution DOFs of this element.
unsigned short nDOFsSol
Number of DOFs for the solution of the element.
codi::RealForward su2double
#define SPRINTF
double passivedouble
#define MPI_COMM_WORLD
#define MPI_INT
CBaseMPIWrapper::Status * MPI_STATUS_IGNORE
#define MPI_MAX
#define CURRENT_FUNCTION
#define MPI_UNSIGNED_LONG
#define MPI_SUM
#define MPI_DOUBLE
#define MPI_CHAR
#define MPI_UNSIGNED_SHORT
double GetValue(const su2double &data)
Get the (primitive) value of the datatype (needs to be implemented for each new type).
short Short(const su2double &data)
Casts the primitive value to short (uses GetValue, already implemented for each type).
int Int(const su2double &data)
Casts the primitive value to int (uses GetValue, already implemented for each type).
double GetDerivative(const su2double &data)
Get the derivative value of the datatype (needs to be implemented for each new type).
const int MASTER_NODE
Master node for MPI parallelization.
const su2double PI_NUMBER
Pi number.
@ NO_HYBRIDRANSLES
No turbulence model.
@ NO
Boolean definition of no.
@ YES
Boolean definition of yes.
@ SU2_DEF
Running the SU2_DEF software.
@ SU2_DOT
Running the SU2_DOT software.
@ D_AOA
Derivative with respect to the angle of attack.
@ D_TEMPERATURE
Derivative with respect to the freestream temperature.
@ D_PRESSURE
Derivative with respect to the freestream pressure.
@ D_DESIGN
@ D_REYNOLDS
@ D_DENSITY
@ D_VISCOSITY
@ D_MACH
Derivative with respect to the mach number.
@ D_TURB2LAM
@ NO_DERIVATIVE
@ D_SIDESLIP
@ PARAVIEW_BINARY
Paraview binary format for the solution output.
@ FIELDVIEW
FieldView format for the solution output.
@ TECPLOT_BINARY
Tecplot binary format for the solution output.
@ TECPLOT
Tecplot format for the solution output.
@ FIELDVIEW_BINARY
FieldView binary format for the solution output.
@ PARAVIEW
Paraview ASCII format for the solution output.
@ DYNAMIC
Use a time stepping strategy for dynamic computations.
const su2double EPS
Error scale.
const int FLOW_SOL
Position of the mean flow solution in the solver container array.
const unsigned short N_POINTS_LINE
General output & CGNS defines.
const unsigned short N_POINTS_QUADRILATERAL
General output & CGNS defines.
@ SPACE_UPWIND
Upwind convective numerical method.
@ SPACE_CENTERED
Space centered convective numerical method.
const unsigned int INST_0
Definition of the first instance per grid level.
const unsigned short N_POINTS_PYRAMID
General output & CGNS defines.
@ CONSTANT_CONDUCTIVITY
_____.
@ CONSTANT_PRANDTL
@ LARGE_DEFORMATIONS
Definition of Neo-Hookean material.
@ SMALL_DEFORMATIONS
Definition of linear elastic material.
@ INCOMPRESSIBLE
Definition of incompressible solver.
@ COMPRESSIBLE
Definition of compressible solver.
@ NACELLE
Nacelle analysis.
@ WING
Wing analysis.
@ FUSELAGE
Fuselage analysis.
const unsigned int MESH_0
Definition of the finest grid level.
@ BUFFET_SENSOR
Sensor for detecting separation.
@ REFERENCE_GEOMETRY
Norm of displacements with respect to target geometry.
@ REFERENCE_NODE
Objective function defined as the difference of a particular node respect to a reference position.
@ TRIANGLE
VTK nomenclature for defining a triangle element.
@ PYRAMID
VTK nomenclature for defining a pyramid element.
@ PRISM
VTK nomenclature for defining a prism element.
@ QUADRILATERAL
VTK nomenclature for defining a quadrilateral element.
@ HEXAHEDRON
VTK nomenclature for defining a hexahedron element.
@ LINE
VTK nomenclature for defining a line element.
@ TETRAHEDRON
VTK nomenclature for defining a tetrahedron element.
const int ADJFLOW_SOL
Position of the continuous adjoint flow solution in the solver container array.
@ HARMONIC_BALANCE
Use a harmonic balance source term.
@ DT_STEPPING_1ST
Use a dual time stepping strategy for unsteady computations (1st order).
@ TIME_STEPPING
Use a time stepping strategy for unsteady computations.
@ DT_STEPPING_2ND
Use a dual time stepping strategy for unsteady computations (2nd order).
const int TURB_SOL
Position of the turbulence model solution in the solver container array.
@ HEAT_EQUATION_FVM
Definition of the finite volume heat solver.
@ FEM_NAVIER_STOKES
Definition of the finite element Navier-Stokes' solver.
@ RANS
Definition of the Reynolds-averaged Navier-Stokes' (RANS) solver.
@ NAVIER_STOKES
Definition of the Navier-Stokes' solver.
@ DISC_ADJ_NAVIER_STOKES
@ ADJ_NAVIER_STOKES
Definition of the continuous adjoint Navier-Stokes' solver.
@ ADJ_EULER
Definition of the continuous adjoint Euler's solver.
@ DISC_ADJ_RANS
@ FEM_RANS
Definition of the finite element Reynolds-averaged Navier-Stokes' (RANS) solver.
@ ADJ_RANS
Definition of the continuous adjoint Reynolds-averaged Navier-Stokes' (RANS) solver.
@ FEM_EULER
Definition of the finite element Euler's solver.
@ DISC_ADJ_EULER
@ EULER
Definition of the Euler's solver.
@ FEM_LES
Definition of the finite element Large Eddy Simulation Navier-Stokes' (LES) solver.
@ FEM_ELASTICITY
Definition of a FEM solver.
@ DISC_ADJ_FEM
@ NO_ROELOWDISS
No Roe Low Dissipation model.
@ SUTHERLAND
@ CONSTANT_VISCOSITY
_____.
const int FEA_SOL
Position of the FEA equation in the solution solver array.
@ AVERAGE_MASSFLUX
Mass-flux weighted average.
@ AVERAGE_AREA
Area-weighted average.
@ RESFEM_ABSOLUTE
Absolute criteria: abs(Res).
@ RESFEM_RELATIVE
Relative criteria: Res/Res0.
const unsigned short N_POINTS_HEXAHEDRON
General output & CGNS defines.
const unsigned short N_POINTS_TETRAHEDRON
General output & CGNS defines.
const int SINGLE_NODE
There is only a node in the MPI parallelization.
const int CGNS_STRING_SIZE
Length of strings used in the CGNS format.
const unsigned short N_POINTS_TRIANGLE
General output & CGNS defines.
@ EULER_WALL
Boundary Euler wall definition.
@ ISOTHERMAL
No slip isothermal wall boundary condition.
@ TRANSPIRATION
Transpiration definition.
@ SEND_RECEIVE
Boundary send-receive definition.
@ INLET_FLOW
Boundary inlet flow definition.
@ HEAT_FLUX
No slip constant heat flux wall boundary condition.
@ NEARFIELD_BOUNDARY
Near-Field boundary definition.
const unsigned int ZONE_0
Definition of the first grid domain.
@ FREESTREAM_PRESS_EQ_ONE
Non-dimensional compressible simulation with freestream pressure equal to 1.0.
@ DIMENSIONAL
Dimensional simulation (compressible or incompressible).
@ FREESTREAM_VEL_EQ_MACH
Non-dimensional compressible simulation with freestream velocity equal to Mach number.
@ INITIAL_VALUES
Non-dimensional incompressible simulation based on intial values for external flow.
@ REFERENCE_VALUES
Non-dimensional incompressible simulation based on custom reference values.
@ FREESTREAM_VEL_EQ_ONE
Non-dimensional compressible simulation with freestream pressure equal to 1.0.
const unsigned int MAX_STRING_SIZE
Maximum number of domains.
@ IDEAL_GAS
_____.
@ CONSTANT_DENSITY
@ STANDARD_AIR
@ INC_IDEAL_GAS
@ VW_GAS
@ PR_GAS
const int ADJFEA_SOL
Position of the FEA adjoint equation in the solution solver array.
const int ADJTURB_SOL
Position of the continuous adjoint turbulence solution in the solver container array.
const int TRANS_SOL
Position of the transition model solution in the solver container array.
@ SA_COMP
Kind of Turbulent model (Spalart-Allmaras Compressibility Correction).
@ SA_E
Kind of Turbulent model (Spalart-Allmaras Edwards).
@ SA_E_COMP
Kind of Turbulent model (Spalart-Allmaras Edwards with Compressibility Correction).
@ SST
Kind of Turbulence model (Menter SST).
@ SA_NEG
Kind of Turbulent model (Spalart-Allmaras).
@ SA
Kind of Turbulent model (Spalart-Allmaras).
const unsigned short N_POINTS_PRISM
General output & CGNS defines.
@ BOUSSINESQ
@ VARIABLE
@ CONSTANT
@ IMPLICIT_LES
Implicit LES, i.e. no explicit SGS model.
@ BC
Kind of transition model (BAS-CAKMAKCIOGLU (BC) for Spalart-Allmaras).
@ LM
Kind of transition model (LM for Spalart-Allmaras).
const int HEAT_SOL
Position of the heat equation in the solution solver array.
@ US
Definition of incompressible solver.
@ SI
Definition of compressible solver.